2010-08-28 38 views
11

Ổ cắm có thể được đóng từ một sợi khác khi gửi/recv trên cùng một ổ cắm không?Ổ cắm có thể được đóng từ một sợi khác khi gửi/recv trên cùng một ổ cắm không?

Giả sử một chủ đề đang chặn cuộc gọi recv và một chuỗi khác đóng cùng một ổ cắm, luồng trong cuộc gọi recv có biết điều này và thoát ra an toàn không?

Tôi muốn biết liệu hành vi sẽ khác nhau giữa các hệ điều hành/nền tảng khác nhau hay không. Nếu có, nó sẽ hoạt động như thế nào trong Solaris?

Trả lời

2

Tôi không biết triển khai ngăn xếp mạng Solaris nhưng tôi sẽ giải thích lý do/giải thích lý do tại sao nó phải an toàn.

  • Chủ đề A đi vào một số lệnh gọi hệ thống chặn, nói read(2), cho ổ cắm đã cho này. Không có dữ liệu trong bộ đệm nhận ổ cắm, do đó, luồng A được lấy ra khỏi bộ xử lý được đặt vào hàng đợi chờ cho ổ cắm này. Không có sự kiện ngăn xếp mạng nào được khởi tạo ở đây, trạng thái kết nối (giả sử TCP) không thay đổi.
  • Sự cố B chủ đề close(2) trên ổ cắm. Trong khi cấu trúc socket hạt nhân bị khóa trong khi thread B đang truy cập nó, không có luồng nào khác đang giữ khóa đó (luồng A đã giải phóng khóa khi nó được đặt vào chế độ chờ đợi). Giả sử không có dữ liệu xuất sắc trong các ổ cắm gửi đệm, một gói FIN được gửi và kết nối vào trạng thái FIN WAIT 1 (một lần nữa tôi giả TCP đây, xem connection state diagram)
  • Tôi đoán rằng sự thay đổi trạng thái kết nối ổ cắm sẽ tạo ra một wakeup cho tất cả các chủ đề bị chặn trên socket đã cho. Đó là luồng A sẽ nhập vào một trạng thái runnable và phát hiện ra rằng kết nối đang đóng. Việc chờ đợi có thể được nhập lại nếu bên kia chưa gửi FIN riêng của mình hoặc cuộc gọi hệ thống sẽ trở lại với eof nếu không.

Trong mọi trường hợp, cấu trúc hạt nhân bên trong sẽ được bảo vệ khỏi truy cập đồng thời không phù hợp. Điều này không có nghĩa là bạn nên làm socket I/O từ nhiều luồng. Tôi sẽ khuyên bạn nên xem xét các ổ cắm không chặn, máy nhà nước và các khung công tác như libevent.

0

Có, bạn có thể đóng ổ cắm từ một sợi khác. Bất kỳ chủ đề bị chặn/bận nào đang sử dụng ổ cắm đó sẽ báo cáo lỗi phù hợp.

+6

Trong linux atleast nó dường như không báo cáo như thế. Một chuỗi recv bị chặn vẫn bị chặn, ngay cả khi chúng ta gọi gần từ một luồng khác. – Jay

2

Đối với tôi, shutdown() ổ cắm từ thread khác thực hiện công việc trong Linux

+2

Chào mừng bạn đến với stackoverflow.com. Bạn có thể cải thiện câu trả lời của bạn bằng cách cung cấp một tham chiếu đến một số loại tài liệu mà khẳng định điều này hoặc cung cấp một ví dụ ngắn. Câu trả lời "làm việc cho bạn" không hữu ích, bởi vì nó _might_ không hoạt động với người khác. – stefan

1

Nếu một thread bị chặn trên recv() hoặc send() khi ổ cắm được đóng bởi một sợi khác nhau, các chủ đề bị chặn sẽ nhận được một lỗi. Tuy nhiên, rất khó để phát hiện hành động khắc phục chính xác sau khi nhận được lỗi. Điều này là do số mô tả tập tin liên quan đến socket có thể đã được chọn bởi một thread khác, và thread bị chặn hiện đã được đánh thức trên một lỗi cho một socket "hợp lệ". Trong trường hợp này, chủ đề được đánh thức nên không phải gọi số close() chính nó.

Chủ đề đánh thức sẽ cần một số cách để phân biệt xem lỗi có được tạo ra bởi kết nối hay không. , trong trường hợp đó nó chỉ nên lỗi mà không làm bất cứ điều gì thêm vào ổ cắm.

3

Trong linux đóng một ổ cắm sẽ không thức dậy recv().Ngoài ra, như @jxh nói:

Nếu một thread bị chặn trên recv() hoặc send() khi ổ cắm được đóng bởi một sợi khác nhau, các chủ đề bị chặn sẽ nhận được một lỗi. Tuy nhiên, rất khó để phát hiện hành động khắc phục chính xác sau khi nhận được lỗi. Điều này là do số mô tả tập tin kết hợp với ổ cắm có thể đã được chọn bởi một luồng khác nhau và chuỗi bị chặn hiện đã bị đánh thức do lỗi cho ổ cắm "hợp lệ" . Trong trường hợp này, chủ đề được đánh thức không nên tự gọi số đóng().

Các thức dậy chủ đề sẽ cần một số cách để phân biệt cho dù lỗi được tạo ra bởi các kết nối (ví dụ như lỗi mạng) mà đòi hỏi nó phải gọi close(), hoặc nếu lỗi được tạo ra bởi một thread khác nhau có gọi là close() trên nó, trong trường hợp nó nên chỉ lỗi ra mà không làm bất cứ điều gì thêm vào ổ cắm.

Vì vậy, cách tốt nhất để tránh cả hai vấn đề là gọi shutdown() thay vì close(). shutdown() sẽ làm cho bộ mô tả tệp vẫn khả dụng, do đó sẽ không được phân bổ bởi một bộ mô tả khác, cũng sẽ đánh thức recv() với lỗi và chuỗi có cuộc gọi recv() có thể đóng ổ cắm theo cách thông thường, như một lỗi bình thường đã xảy ra.

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