Một Lỗi Phát Sinh Từ Hàm Recv - nói dối e blog

Một Lỗi Phát Sinh Từ Hàm Recv

Hôm nay tựa game đấu bài “Card Duel” chính thức ra mắt phiên bản mới. Khi gần như toàn bộ gói cập nhật đã được phát hành, bỗng nhiên phát hiện ra một lỗi nghiêm trọng. Không khí lúc đó căng thẳng đến mức nào! May mắn thay, tôi đã giữ được bình tĩnh và dành nửa tiếng đồng hồ mày mò rà soát từng dòng mã nguồn, cuối cùng cũng tìm ra nguyên nhân.

Vì lần này cần triển khai nhiều điểm truy cập mạng để giải quyết vấn đề kết nối giữa các nhà cung cấp dịch vụ mạng như VNNET, VNPT và mạng giáo dục, tôi đã đăng ký sử dụng nhiều máy chủ từ các mạng khác nhau. Những máy chủ mới này chạy hệ điều hành Debian/Linux, khác với môi trường phát triển FreeBSD mà nhóm chúng tôi vẫn dùng. Việc một chương trình trước đây chạy ổn định trên FreeBSD nhưng lại phát sinh lỗi trên Linux khiến tôi ban đầu rất bối rối.

Sau khi kiểm tra kỹ lưỡng, tôi phát hiện lỗi nằm ở một lời gọi hàm recv. Dùng gdb attach vào tiến trình bị treo, quả nhiên phát hiện một lời gọi recv không trả về kết quả như mong đợi.

Nguyên nhân chính là do việc cố ý dùng chế độ chặn (blocking) để recv với độ dài 0 byte. Cụ thể khi gọi: recv(fd,buf,0,MSG_WAITALL); Trên hệ thống Linux, lời gọi hệ thống này sẽ rơi vào trạng thái treo vô hạn mà không có phản hồi.

Đồng nghiệp của tôi đã kiểm chứng và cho biết trên FreeBSD, hành vi tương tự sẽ trả về giá trị 0 và thiết lập một mã lỗi errno đặc biệt. Tuy nhiên hành vi này không gây ảnh hưởng nghiêm trọng đến hoạt động của chương trình.

Tất nhiên, đây là lỗi phát sinh từ cách triển khai chương trình. Việc truyền tham số độ dài bằng 0 vào hàm recv là hành vi không được định nghĩa trong tiêu chuẩn. Chỉ là tôi cảm thấy cách xử lý của FreeBSD có phần “nhân văn” hơn mà thôi, haha.

Nhân tiện, trong hai ngày qua tôi phát hiện ra syslogd mặc định trên Debian không thực sự tiện dụng. Nó thậm chí không hỗ trợ cấu hình lọc theo chuỗi định danh (ident) như cách chúng tôi vẫn làm trên FreeBSD. Có lẽ đây chính là lý do vì sao các đồng nghiệp phát triển trên Linux lại không có thói quen sử dụng syslog để ghi log chương trình.

Hay có thể là do tôi chưa biết cách sử dụng linh hoạt syslogd trên Linux nhỉ?

0%