tags:

views:

80

answers:

2

In Linux if we call blocking recv from one thread and close for the same socket from another thread, recv doesn't exit.

Why?

+2  A: 

Check that all file descriptors for the socket have been closed. If any remain open at the "remote end" (assuming this is the one you attempt to close), the "peer has not performed an orderly shutdown".

If this still doesn't work, call shutdown(sock, SHUT_RDWR) on the remote end, this will shut the socket down regardless of reference counts.

Matt Joiner
+2  A: 

The "why" is simply that that's how it works, by design.

Within the kernel, the recv() call has called fget() on the struct file corresponding to the file descriptor, and this will prevent it from being deallocated until the corresponding fput().

You will simply have to change your design (your design is inherently racy anyway - for this to happen, you must have no locking protecting the file descriptor in userspace, which means that the close() could have happened just before the recv() call - and the file descriptor even been reused for something else).


If you want to wake up another thread that's blocking on a file descriptor, you should have it block on select() instead, with a pipe included in the file descriptor set that can be written to by the main thread.

caf
@caf, if I call close before calling recv, it should work, but once the call is in recv, and if I call close from another thread, it doesn't get deallocated. Is this correct?
Jay
@Jay: Once you've called `close()`, you should *not* call `recv()` on the file descriptor. If you're lucky you'll just get `EBADF`, but if you're unlucky you could read from a completely different socket newly opened by another thread.
caf
@caf: I think you are missing the point. Pater is trying to call close() on a socket that is ALREADY inside of recv() to force recv() to exit immediately. This works on other systems, but is not working on Linux.
Remy Lebeau - TeamB
@Remy: I know that, and as I said in my answer - that behaviour is by design. My first comment is in relation to the OPs comment.
caf