1

I am writing a simple multithreaded chat server in Python3. Sometimes i want to interrupt another thread that is waiting in socket.recv() to allow the theread to perform cleanup tasks.

Is calling socket.shutdown(socket.SHUT_RDWR) from another thread safe?

kinokijuf
  • 968
  • 1
  • 11
  • 33
  • You may want to look into [select()](https://docs.python.org/3/library/select.html) You can then listen to multiple inputs and choose whichever is ready to provide you with data. – TemporalWolf Nov 18 '16 at 23:28
  • @TemporalWolf I know about selectors. Unfortunately, this is a homework assignment, and we must use multithreaded raw sockets. – kinokijuf Nov 18 '16 at 23:30
  • [This answer](http://stackoverflow.com/a/27790293/1005379) and [this one](http://stackoverflow.com/a/8050401/1005379) seems to indicate that this is in fact the recommended way, but i'm not sure how it works in a high-level language such as Python – kinokijuf Nov 18 '16 at 23:34
  • I'd encourage you to review [how to ask homework questions](http://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions). Show us what you've done/tried. – TemporalWolf Nov 18 '16 at 23:36

1 Answers1

2

Calling socket.shutdown from another thread is reasonably safe, and, as @kinokikuf mentioned, is an appropriate way to terminate a blocking recv() in another thread, as long as you can guarantee that the socket is not yet closed when the call to shutdown() happens.

If you cannot guarantee that the socket isn't yet closed, you may get an exception when calling shutdown or you might even terminate another unrelated connection if a race-condition happens and the socket handle is reused by the OS!

The Linux man page for the shutdown() system call doesn't explicitly state that blocking recv() calls will be terminated, only that "further receptions and transmissions will be disallowed". But in practice this seems to include blocking recv() calls on the same socket on both Unixoid systems and Windows.

Another way would be to use socket.settimeout() to circumvent the indefinite blocking problem and regularly check (e.g. with global variables) inside the thread if the connection should be closed.

Yet another reasonable way to interrupt the recv() would be to send a non-lethal signal to the thread, which will interrupt the recv() system call, but there seems to be no wrapper for the low-level pthread_kill function in Python and since Python 3.5 system calls will be automatically restarted if interrupted, which makes this option unusable.

cg909
  • 2,247
  • 19
  • 23
  • Thanks! I'm only calling close() from the thread that manages the function, so i'm always shutting down a open socket. – kinokijuf Nov 19 '16 at 14:34