Can a socket be closed from another thread when a send / recv on the same socket is going on?

后端 未结 5 1110
刺人心
刺人心 2021-02-02 15:48

Can a socket be closed from another thread when a send / recv on the same socket is going on?

Suppose one thread is in blocking recv call and another thread closes the s

相关标签:
5条回答
  • 2021-02-02 16:17

    If a thread is blocked on recv() or send() when the socket is closed by a different thread, the blocked thread will receive an error. However, it is difficult to detect the correct remedial action after receiving the error. This is because the file descriptor number associated with the socket may have been picked up by yet a different thread, and the blocked thread has now been woken up on an error for a "valid" socket. In such a case, the woken up thread should not call close() itself.

    The woken up thread will need some way to differentiate whether the error was generated by the connection (e.g. a network error) that requires it to call close(), or if the error was generated by a different thread having called close() on it, in which case it should just error out without doing anything further to the socket.

    0 讨论(0)
  • 2021-02-02 16:19

    I don't know Solaris network stack implementation but I'll throw out my theory/explanation of why it should be safe.

    • Thread A enters some blocking system call, say read(2), for this given socket. There's no data in socket receive buffer, so thread A is taken off the processor an put onto wait queue for this socket. No network stack events are initiated here, connection state (assuming TCP) has not changed.
    • Thread B issues close(2) on the socket. While kernel socket structure should be locked while thread B is accessing it, no other thread is holding that lock (thread A released the lock when it was put to sleep-wait). Assuming there's no outstanding data in the socket send buffer, a FIN packet is sent and the connection enters the FIN WAIT 1 state (again I assume TCP here, see connection state diagram)
    • I'm guessing that socket connection state change would generate a wakeup for all threads blocked on given socket. That is thread A would enter a runnable state and discover that connection is closing. The wait might be re-entered if the other side has not sent its own FIN, or the system call would return with eof otherwise.

    In any case, internal kernel structures will be protected from inappropriate concurrent access. This does not mean it's a good idea to do socket I/O from multiple threads. I would advise to look into non-blocking sockets, state machines, and frameworks like libevent.

    0 讨论(0)
  • 2021-02-02 16:22

    Yes, it is ok to close the socket from another thread. Any blocked/busy threads that are using that socket will report a suitable error.

    0 讨论(0)
  • 2021-02-02 16:26

    In linux closing a socket won't wake up recv(). Also, as @jxh says:

    If a thread is blocked on recv() or send() when the socket is closed by a different thread, the blocked thread will receive an error. However, it is difficult to detect the correct remedial action after receiving the error. This is because the file descriptor number associated with the socket may have been picked up by yet a different thread, and the blocked thread has now been woken up on an error for a "valid" socket. In such a case, the woken up thread should not call close() itself.

    The woken up thread will need some way to differentiate whether the error was generated by the connection (e.g. a network error) that requires it to call close(), or if the error was generated by a different thread having called close() on it, in which case it should just error out without doing anything further to the socket.

    So the best way to avoid both problems is to call shutdown() instead of close(). shutdown() will make the file descriptor still available, so won't be allocated by another descriptor, also will wake up recv() with an error and the thread with the recv() call can close the socket the normal way, like a normal error happened.

    0 讨论(0)
  • 2021-02-02 16:34

    For me, shutdown() socket from another thread do the job in Linux

    0 讨论(0)
提交回复
热议问题