2011-12-27 34 views
8

Tôi đã có một máy chủ đa luồng (sử dụng các chủ đề POSIX), với một luồng cho mỗi kết nối liên tục. Trong một trong các chủ đề, đầu kia của kết nối đóng lại, dẫn đến một SIGPIPE đang được gửi đi. Có một (tốt nhất là di động) để xác định thread nào (và do đó kết nối) điều này xảy ra vì vậy tôi có thể có trình xử lý tín hiệu của tôi hoặc làm dọn dẹp luồng/kết nối làm việc hoặc đặt cờ sao cho chuỗi chính và công nhân tương ứng thấy rằng họ cần phải làm điều đó sau?Chủ đề/tín hiệu POSIX: Cách di động để xác định luồng tín hiệu nào được phân phối?

EDIT: Tôi tự hỏi nếu tôi có thể sử dụng & errno, lưu trữ nó trong một mảng toàn cầu và liên kết nó với định danh của máy chủ cho chủ đề, và sau đó tìm kiếm & errno trong bộ xử lý tín hiệu. Liệu các errno cụ thể của thread có thể được hiển thị cho bộ xử lý tín hiệu? Là sự hiểu biết của tôi về cách threadsafe errno hoạt động ngay cả trong ballpark?

+0

Nếu tín hiệu được gửi đến một chuỗi cụ thể thì luồng đó sẽ xử lý tín hiệu. Đó là những gì cung cấp một tín hiệu cho một chủ đề cụ thể có nghĩa là. Tôi không hiểu những gì có để kiểm tra? –

+0

Bởi vì điều đó không cho tôi biết đó là chủ đề cụ thể. –

+0

Tôi không hiểu, chủ đề là chủ đề xử lý tín hiệu. Bạn cần biết thông tin gì về chuỗi hiện tại? –

Trả lời

12

Tôi không nghĩ vậy, không. Một giải pháp tốt hơn cho các máy chủ đa luồng là để ngăn chặn tín hiệu SIGPIPE (bằng cách gọi signal(SIGPIPE, SIG_IGN) như là một phần của chương trình khởi động thường trình) và sau đó có giao dịch với giá trị lỗi (-1/EPIPE) trả về send() thay thế.

Tín hiệu và đa luồng không kết hợp tốt.

+0

Tôi đã xem xét khả năng đó; vấn đề là sau đó tôi sẽ không phát hiện sự ngắt kết nối cho đến khi thời gian tiếp theo tôi cần phải gửi dữ liệu xuống kết nối đó - mà có khả năng có thể không bao giờ. –

+1

Điều này có thể dễ dàng bị bắt bằng cách chọn trên fd đó cho lỗi chỉ –

+1

Mmm, bạn nói đúng. Tôi đang sử dụng epoll và quên EPOLLHUP. –

0

Cách tiếp cận của tôi là có bộ xử lý tín hiệu cho SIGPIPE chỉ ghi ID luồng của nó vào biến toàn cục và sử dụng một số cơ chế khác để báo hiệu điều này cho luồng, cần xử lý nó.

+0

Vâng, điều đó vẫn làm nảy sinh cùng một câu hỏi cơ bản về cách di chuyển, an toàn tín hiệu, tôi phải tìm ra chủ đề cụ thể nào xảy ra, vì tôi phải tìm ra ID luồng là gì. –

+0

Điều này khá dễ dàng: ví dụ: nâng cao một sự kiện thông qua bất kỳ cơ chế sự kiện nào mà hệ thống của bạn hỗ trợ (bao gồm việc gửi thứ gì đó đến đường ống) và có một chuỗi lắng nghe những sự kiện này (bao gồm chọn trên đường ống đó), đọc biến toàn cầu (khóa được bảo vệ) nếu cần. –

+0

Tôi nghĩ rằng một vấn đề với cách tiếp cận toàn cầu biến là điều xảy ra nếu hai tín hiệu được nâng lên nhanh chóng - tín hiệu thứ hai có thể ghi đè lên giá trị được ghi bởi tín hiệu đầu tiên trước khi xử lý đầu tiên được thực thi. Bạn sẽ cần một hàng đợi FIFO được khóa bảo vệ ít nhất ... nhưng sau đó bạn gặp phải vấn đề thứ hai, đó là bạn không được phép khóa một mutex từ bên trong một trình xử lý tín hiệu. –

0

Điều gì về việc sử dụng biến toàn cầu (chuỗi địa chỉ được khai báo) để lưu trữ id-thread, khởi tạo nó trên tạo chuỗi và tham chiếu đến nó trong trình xử lý tín hiệu của chuỗi.

Để biết chi tiết GCC về vấn đề này xin vui lòng xem tại đây: http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html hoặc tổng quát hơn ở đây: http://en.wikipedia.org/wiki/Thread-local_storage

+0

Chức năng lưu trữ chủ đề cục bộ không an toàn về tín hiệu, vì tôi hiểu nó. –

+0

@Steely Dan: Tôi không đề cập đến dữ liệu theo chủ đề cụ thể bằng cách sử dụng các chức năng để truy cập vào nó. Vui lòng xem tài liệu tham khảo mà tôi vừa thêm vào bài đăng của tôi, thay vào đó là những gì tôi đã đề cập đến. – alk

1

Bạn có thể sử dụng một cách an toàn pthread_self trong xử lý tín hiệu. Đó là async-signal-safe.

Câu trả lời này là dành cho hậu thế. Tôi không khuyên bạn nên tiếp cận kỹ thuật này. Các câu trả lời và nhận xét khác, đề xuất một cách tiếp cận khác, sẽ tốt hơn để thực hiện.

Vào thời điểm câu hỏi này được đặt ra, sự an toàn của pthread_self không nhất thiết phải rõ ràng. POSIX: Bản sửa đổi kỹ thuật số 1 năm 2008, năm 2013 (hai năm sau khi câu hỏi này được hỏi), làm rõ rằng pthread_self rõ ràng là không đồng bộ-tín hiệu an toàn, như đã nêu trong số Linux signal(7) man page.

Có liên quan, bạn đã đề cập trong nhận xét rằng bạn không chắc liệu hạt nhân "gửi [SIGPIPE] đến bất kỳ chuỗi nào không bị chặn". Đó là một mối quan tâm tốt - nó là một tín hiệu hướng quá trình hoặc tín hiệu chỉ đạo? - và, may mắn thay, thất lạc. Một SIGPIPE do kernel tạo ra là một tín hiệu "được tạo đồng bộ" để đáp ứng với một số cuộc gọi I/O, và được gửi đến chuỗi gọi. Điều này đã được làm sáng tỏ rõ ràng trong Corrigendum 2 (2004) cho POSIX: 2001 để nói rằng một SIGPIPE để đáp ứng với một số write"sent to the thread" (được thêm vào).

Các vấn đề liên quan