1

I have a simple server program, written in C on Debian using the pthread lib. The program handles the communication between some clients which want to share files. For each client there is a handler thread. Now, at some point, each thread will block on recv() waiting for any client file requests. If one of the clients asks for a specific file owned, by another client, the server has to get this file from its owner, through its handler thread, and then deliver the file to the client which requested it, through its handler thread. As all the threads are blocked on the recv() calls, how can they be noticed by other threads that they have to request a file to the client they are handling? Is there any way to "interrupt" the recv(), serve the request and then go back to the recv()?

turbopapero
  • 932
  • 6
  • 17
  • Have non-blocking sockets, and use `select`/`poll`? – Some programmer dude Apr 17 '15 at 16:29
  • Unfortunately one of the project requirements is that threads have to block on the recv. Would it be possibile to use a signal SIGUSR1 to interrupt the blocking recv? – turbopapero Apr 17 '15 at 16:48
  • The tricky part with mixing threads and signals is making sure the signal gets sent to the correct thread. Non-blocking recv() is a better solution because a thread blocked inside select() can be woken up cleanly by sending it a byte on another socket. That said, if you must try the signals route, see this: http://stackoverflow.com/questions/2575106/posix-threads-and-signals – Jeremy Friesner Apr 17 '15 at 16:51
  • If you use a select you can break the recv() block in various ways. E.g. by adding a timeout, that breaks the recv() after some time, og e.g. by including pipe in the select .. Write to the pipe, and the thread unblocks. Look [here](http://stackoverflow.com/questions/384391/how-to-signal-select-to-return-immediately) – Ebbe M. Pedersen Apr 17 '15 at 16:53
  • "*Would it be possibile to use a signal SIGUSR1 to interrupt the blocking recv*" yes. Use `pthread_kill()` for this. – alk Apr 19 '15 at 08:32

1 Answers1

2

The classic way to do this is to create a pipe() for each thread, and instead of blocking on the recv() call, the thread blocks in poll() monitoring both the socket and the read end file descriptor of the pipe. When poll() returns, if the socket is readable then call recv(); if the pipe is readable then read from it and check for requests from other threads.

When you want to make a request to another thread, you can wake it up by writing to that thread's pipe.

caf
  • 233,326
  • 40
  • 323
  • 462