0

I am coding a game-server that allows up to 1100 concurrent connections using thread-per-connection approach. Every time a login packet is read from the client socket I want to be able to give it 5 seconds to connect, otherwise gracefully the connection and release the thread to the pool.

I know about alarm() for sending the process a SIGALRM, but which thread receives the signal is undefined behavior. I also tried the setitimer function, but it also sends the signal to the process. Blocking the signal in all threads but ours is impossible because I need to get the signals in all 5 threads.

Is there any way of doing this without changing the entire server architecture?

Note: This is not a personal project, so changing the thread-per-connection model is not an option, please consider these answers out-of-topic.

Svtyros
  • 55
  • 8
  • There are many approaches to managing timeouts... but there's no good way to direct signals to a specific thread. Consider creating a timeout thread that tests an ordered linked list of nodes containing thread ID and timestamp for timeouts... every login packet could update a timestamp and move the thread-timestamp node structure to the end of the linked list... Though what I really recommend is to throw the thread-per-client model to the garbage and switch to an vented library (`libev` / `libuv` / `facil.io`... there's tons of them). – Myst Jul 22 '19 at 23:00
  • I don’t understand why you need to send a signal? Just release the thread to the pool as you already do? The thread handling the connection should keep track of the time anyhow. – Fredrik Jul 22 '19 at 23:03
  • It is possible via a variety of mechanisms to deliver signals to specific threads. For example, you can do it with `pthread_kill()`. But if you're doing a thread-per-connection setup then that seems an odd approach. What thread is going to *dispatch* the signal, if not the very same one that you want to receive it, since that's the one responsible for the connection? And in that case, what's the point? – John Bollinger Jul 24 '19 at 21:29
  • Of course, thread-per-connection for 1000+ simultaneous connections seems a questionable choice to begin with, but sending a signal is even less appropriate for the alternatives that come to mind. – John Bollinger Jul 24 '19 at 21:31

1 Answers1

3

Threads and signals don't mix well, for the reasons you found out -- it's indeterminate which thread will receive the signal.

A better way to get a timeout within a thread is to set the socket to non-blocking mode and then run a while-loop around select() and recv(). Use the timeout argument to select() to ensure that select() will wake up at the end of your 5-second deadline, pass your socket in as part of the read-fd_set argument, and keep in mind that if the connection is TCP, the data from your socket may arrive in multiple small chunks (hence the while-loop, to collect all of them into a buffer).

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234