Skip to content
Advertisement

Linux server C code stalls after receiving a signal

I have a problem with this simple server code, it works as expected until it receives a signal. For debug I print server and client file descriptors before calling select with the line:

JavaScript

When running normally it keeps printing

JavaScript

but when it receives a signal it prints this line once

JavaScript

and then the program stalls.

Using GDB I put a breakpoint in the signal_handler and when it breaks I can’t watch client_socket_fd variable, gdb says

JavaScript

And it doesn’t return properly from the signal_handler function.. if I watch the back trace:

JavaScript

I don’t know how to debug deeper.

This is the main code:

JavaScript

I don’t know what else can I do for debugging this issue and I am stuck. Any help will be very appreciated!

EDITED:

This is the strace output when it fails, as you can see it prints (and select uses) the right file descriptors and then, after the signal occurs, the client_socket_fd is wrong because accept fails with EAGAIN. I have commented the exit_properly calls and also the signal handling for SIGTERM and SIGINT. For the SIGWINH signal I do nothing, just return.

STRACE output:

JavaScript

The signal_handler now:

JavaScript

Also tried without the SA_RESTART flag… same result… ?: /

Advertisement

Answer

select() will be interrupted by a signal, return -1, and set errno to EINTR, but your code fails to handle this. Even if you install a signal handler with the SA_RESTART , there are still a number of system calls that will be interrupted, return an error condition and set errno to EINTR.

See the “Interruption of system calls and library functions by signal handlers” section at http://man7.org/linux/man-pages/man7/signal.7.html/

If select fails, your code goes on to check the readfds like this:

JavaScript

However, if select() fails, the fd_set variables you pass to it are in an indeterministic state, you should not rely on their values.

Instead, if select fails you should just re-start your loop with e.g. a continue statement like so:

JavaScript
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement