0

I have a server running fine. This servers is a multi-client and it's working fine, but I don't think I'm using the best approach for this and the main point for this assumption is the way I 'exit' application. I'm handling signals and just exiting, but it's not right, I can't even debug using valgrind. In my other apps, I use a global variable to hold app state, for example, pexit and in every thread that runs 'forever', the condition is:

while (!pexit) ....

And in the signal handle I just set 'pexit' to 'true' and everything works fine. But my problem is in listening function, which is 'blocking', therefore I can't use my global variable. Is a better way to do this without blocking?

while ((client_sock = accept(socket_desc, (struct sockaddr *) &client, (socklen_t*) & c))) {
....
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
Jonis Maurin Ceará
  • 449
  • 1
  • 4
  • 11
  • 1
    http://stackoverflow.com/questions/2486335/wake-up-thread-blocked-on-accept-call – pm100 May 15 '17 at 18:46
  • accept blocks until a connection is ready. please check out `man getaddrinfo` for an example of a socket server and client – Ryan May 15 '17 at 18:46
  • The answer probably depends on the OS, which do you use? Generally I wouldn't worry too much about cleaning up at shutdown because the OS cleans up everything anyway. – alain May 15 '17 at 19:02
  • @alain, it's a Linux machine. I'm not sure If I understood, but the problem is not how or when shutdown sockets, but how to keep accepting (for multiple-clients) without blocking, therefore using my 'pabort' to stop waiting and shutdown my app. – Jonis Maurin Ceará May 15 '17 at 19:11
  • You could set the listen socket to non-blocking. BTW your `((client_sock = accept(socket ...` is not correct. accept() will return -1 on error, not zero. – wildplasser May 15 '17 at 19:40
  • You could use `select()` with a timeout to wait until a connection is ready to be accepted, and check at each wakeup whether to exit. You can then control the window within which you can expect an exit instruction to be recognized by means of the lengtjh of the `select()` timeout. – John Bollinger May 15 '17 at 19:49
  • Alternatively, you could interrupt the `accept()` call by sending a signal to the process (which could also be the means by which you cause your exit flag to be set). Provided that signal is neither blocked nor ignored, and that you have not configured automatic restart of system calls upon its receipt, the `accept()` call should then return -1 and set `errno` to `EINTR` (a case for which you might want special handling anyway). – John Bollinger May 15 '17 at 19:52
  • On linux I would use non-blocking sockets with `epoll`. Under heavier loads, an evened design will work far better than a thread-per-client design. You can look up the code in the [facil.io library](http://facil.io) for an evented server example. – Myst May 16 '17 at 06:41

1 Answers1

1

In your main loop, instead of calling accept() directly, use select() to check for an incoming connection. Add socket_desc (the "mother" socket) to the list of file descriptors to be watched for reading, and set a suitable timeout. When select() returns with the bit for socket_desc set, you can call accept() without blocking. And the timeout makes sure that the select() call doesn't block indefinitely.

Hellmar Becker
  • 2,824
  • 12
  • 18