Sửa lỗi 20 năm tuổi trong Enlightenment E16: Khi thuật toán Newton gây ra vòng lặp vô tận
Một lỗi tồn tại từ năm 2006 trong trình quản lý cửa sổ Enlightenment E16 đã được phát hiện và khắc phục. Vấn đề bắt nguồn từ việc triển khai sai thuật toán Newton trong chức năng hiển thị văn bản, khiến máy tính bị treo cứng khi mở các file có tiêu đề dài.

Sửa lỗi 20 năm tuổi trong Enlightenment E16: Khi thuật toán Newton gây ra vòng lặp vô tận
Đối với nhiều người, việc sử dụng một phần mềm ra đời năm 1997 có vẻ là một sự lựa chọn kỳ quặc. Tuy nhiên, với tôi, Enlightenment E16 vẫn là một trình quản lý cửa sổ (window manager) tuyệt vời nhờ tính năng tùy biến cao, nhẹ nhàng và cực kỳ thân thiện với người dùng bàn phím. Gần đây, tôi đã tình cờ phát hiện và khắc phục một lỗi nghiêm trọng đã ẩn mình trong mã nguồn của E16 từ năm 2006, một lỗi có nguồn gốc sâu xa từ việc triển khai sai thuật toán Newton.
Màn hình làm việc Enlightenment E16
Lỗi "đóng băng" màn hình
Vấn đề xuất hiện vào một thời điểm tồi tệ nhất: khi tôi đang gấp rút hoàn thành các slide bài giảng. Tôi đã mở một file PDF chứa tài liệu bài tập trên Atril và bất ngờ, toàn bộ màn hình desktop bị đóng băng cứng. Sau khi buộc phải kết thúc phiên X11 từ TTY, tôi nhận thấy lỗi này có tính xác định cao: mỗi khi mở file PDF cụ thể đó, máy tính lại treo.
Quá trình điều tra bằng công cụ GDB đã chỉ ra rằng tiến trình không bị deadlock (tắc nghẽn), mà bị kẹt trong một vòng lặp vô tận. Stack trace liên tục trỏ về hàm TextstateTextFitMB trong imlib2, cụ thể là đoạn mã xử việc đo kích thước phông chữ để hiển thị tiêu đề cửa sổ.
Đi sâu vào mã nguồn
Hàm TextstateTextFitMB có nhiệm vụ cắt ngắn tiêu đề cửa sổ quá dài bằng cách thay thế phần giữa chuỗi bằng dấu ba chấm "..." để phù hợp với chiều rộng của thanh tiêu đề. Trong trường hợp của tôi, tiêu đề file PDF "Kickoff.pdf — Introduction to Information Theory Session 1: kickoff & first topic" quá dài so với khoảng 291 pixel cho phép.
Giao diện debug và mã nguồn
Tôi nhận thấy rằng vòng lặp for(;;) trong hàm này đã rơi vào trạng thái dao động (oscillation) giữa hai giá trị của biến nuke_count (số ký tự cần loại bỏ): 8 và 11. Nó thử cắt 8 ký tự, thấy vẫn dài, thử cắt 11 ký tự, thấy quá ngắn, rồi lại quay về 8... và quá trình này lặp lại mãi mãi.
Nguyên nhân cốt lõi: Thuật toán Newton bị lỗi
Vấn đề nằm ở cách thuật toán tính toán bước điều chỉnh nuke_count. Mã nguồn cố gắng sử dụng một phương pháp tương tự thuật toán Newton để hội tụ nhanh chóng về số lượng ký tự cần cắt. Công thức được sử dụng là:
nuke_count -= (nc2 <= 2 * cw) ? 1 : (nc2 + cw / 2) / cw;
Tuy nhiên, triển khai này có khiếm khuyết. Khi bước tính toán quá lớn hoặc không chính xác, nó không đảm bảo sự hội tụ mà lại khiến giá trị nuke_count dao động qua lại giữa hai điểm. Hơn nữa, mã nguồn thiếu các biện pháp bảo vệ để ngăn chặn việc nuke_count trở nên âm hoặc gây chia cho 0.
Giải pháp khắc phục
Để sửa lỗi này, tôi đã áp dụng các thay đổi sau vào mã nguồn của E16 phiên bản 1.0.30:
- Phát hiện dao động: Thêm logic để phát hiện khi vòng lặp không thể tiến bộ (khi
nuke_countthay đổi qua lại giữa các giá trị). Nếu phát hiện这种情况, vòng lặp sẽ thoát hoặc tăngnuke_counttừ từ để đảm bảo kết thúc. - Giới hạn giá trị: Đặt sàn cho
nuke_countlà 1 để tránh tạo ra chuỗi ký tự bị lỗi, và đặt sàn chocw(chiều rộng ký tự trung bình) là 1 để tránh lỗi chia cho 0.
Đoạn vá (patch) thêm các kiểm tra điều kiện cần thiết để đảm bảo thuật toán sẽ luôn kết thúc trong thời gian hữu hạn thay vì chạy vô tận.
Bài học về phần mềm "cổ thụ"
Câu chuyện này là một lời nhắc nhở thú vị về việc lựa chọn phần mềm. Mặc dù phần mềm mới luôn mang đến các tính năng hiện đại, nhưng chúng cũng đi kèm với những lỗi mới và rủi ro từ chuỗi cung ứng (như sự cố backdoor XZ Utils vừa qua). Ngược lại, những phần mềm cũ kỹ, "già cỗi" nhưng được duy trì bởi các nhà phát triển tận tâm như E16, dù có nợ kỹ thuật (technical debt), lại mang lại sự ổn định và khả năng kiểm soát cao hơn đối với người dùng hiểu biết.
Đôi khi, "cũ" không có nghĩa là "tồi", và việc tự mình sửa lỗi trên một hệ thống mà bạn yêu thích mang lại sự thỏa mãn mà không bản cập nhật tự động nào có thể mang lại.



