views:

271

answers:

3

In Linux, if two threads are created and both of them are running, when one of them calls recv() or any IO syscall that blocks when no data is available, what would happen to the whole process?

Will the other thread block also? I guess this depends on how threading is implemented. If thread library is in user space and kernel totally unaware of the threads within process, then process is the scheduling entity and thus both threads got blocked.

Further, if the other thread doesn't block because of this, can it then send() data via the same socket, which is blocking the recv thread? Duplexing?

Any ideas?

+2  A: 

Blocking calls in one thread should not affect other threads.

If the blocked thread locks a mutex prior to entering the blocked call and the second thread attempts to lock the same mutex, then they the second thread would need to wait for the blocking call to finish and for the first thread to release the lock.

Marc
Thanks, then it drops to the 2nd question: can the other non-blocking thread send() data via the same socket while recv() is blocking another? Assume UDP.
Figo
+2  A: 

It's completely possible to implement threads in user-space such that one thread can proceed while another thread block on I/O.

The non-blocked thread should be able to send on the socket while the other thread is blocking on it (I've written such code).

Steve Emmerson
Thanks, that's great news.
Figo
Only possible if the syscalls support nonblocking calls for everything. Very possible to stall all user threads on something like fstat for several seconds.
Zan Lynx
@Zan Lynx: He's talking about Linux, which has the POSIX-complient aio_read() and aio_write() system calls.
Steve Emmerson
@Steve Emmerson: Did you note I said "like fstat?" That is a POSIX call with no async version I am aware of. There are others.
Zan Lynx
+1  A: 

You're absolutely right that the blocking behavior will depend on if the thread is implemented in kernel space, or in user space. If threading is implemented purely in user space (that is, the kernel is completely uninvolved with the threading), then any blocking entry point into the kernel will need to be wrapped with some non-blocking variant that can simulate blocking semantics to its calling "thread" (e.g. using AIO to send / recv data instead of blocking, and the completion callback makes the thread runnable, again).

In Linux (and every other extant major OS I can think of), threading is implemented at the kernel level, or similar, and a blocking call into the kernel will not cause all other threads to block.

Yes, you can send() to a socket for which another thread is blocked on recv().

Aidan Cully
Thanks! a fairly complete answer. good call.
Figo
One more question, if there's data arrived at socket before a thread calls recv(), will the thread actually get those data?
Figo
Yes. That's really the only way it could work, on non-blocking datagram sockets. A couple of little notes, that I intend to be helpful - one, you can experiment with this sort of thing pretty easily. Write a little program that'll `accept` a connection, then `sleep` a while, then call `recv` on the new connection. Use `nc` (netcat) or something to create the connection to your server, and write some data to it immediately. You'll see the server got the same data as you sent. Second note - this is really a third distinct question on what's generally a question-at-a-time forum...
Aidan Cully