0

I have a program that uses epoll to wait for certain events (like data available in a socket, etc). This program is running as a service started by systemd. What I want to achieve is a proper shutdown. So I have installed a signal handler that will catch the SIGTERM. From my understanding, systemd will first send a SIGTERM followed by a SIGKILL after a delay, so the process has the chance for a proper shutdown.

My signal handler looks like this:

struct sigaction act;
::memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_RESTART;
act.sa_handler = sigterm;
if (sigaction(signal, &act, NULL) == -1)
{
    logger_.explode("Error setting up signal %d (%d)", signal, errno);
}

With my function of sigterm beeing:

void sigterm(int signo)
{
    logger_->info("SIGTERM received. Quitting.");
    shutdown_if_->init_shutdown();
}

Whereas shutdown_if_ will trigger a fd to be written to that is hanged into the poll as as quit event (created with pipe).

What I expect to happen: The process will continue as I have catched the SIGTERM and will begin to terminate. Instead of that, after the signal is catched, I will receive a SIGSEGV as something seems to be messed up. When I look at it with a debugger the whole stack seems to be hella messed up (local variables missing, etc).

When I use the shutdown function of the poll in another context that with signals, everything works fine, static code analysis does not find anything as well. I am really stuck here.

Please tell me if you want any more informations, I do not really know how to put this problem.

Nidhoegger
  • 4,973
  • 4
  • 36
  • 81
  • 2
    Is your signal handler doing anything that isn't allowed according to [this](https://en.cppreference.com/w/cpp/utility/program/signal)? (See the *The behavior is undefined if any signal handler performs any of the following* section) – Kevin Oct 26 '18 at 13:09
  • As POSIX, you might be interested in [here](http://www.man7.org/linux/man-pages/man7/signal-safety.7.html) as well. Following @Kevin's comment: `logger_->info` might be critical. I'd assume file IO being involved, seldom a good idea to do in a signal handler... – Aconcagua Oct 26 '18 at 13:26
  • In my experience, signal handlers aren't allowed to do pretty much all the things you want to do in them. – molbdnilo Oct 26 '18 at 13:31
  • Thank you very much, the information is very useful. I am investigating now which calls are not that good in my handler. thanks alot! – Nidhoegger Oct 26 '18 at 16:40
  • Thanks a lot. There were some issues here. What I have done now is to use the fact that epoll gets interrupted with error EINTR when a signal triggers. That way I can just set a bool in the handler and check on EINTR and this bool. If only EINTR is given, restart the poll, if EINTR and the bool are set -> quit poll. Everything works fine now! – Nidhoegger Oct 26 '18 at 16:45
  • make sure you use correct flag, typically you can't just use bool: https://stackoverflow.com/questions/18907477/set-flag-in-signal-handler . Also make sure you take care of reentrancy and multi-threading issues with signals (if this is MT process -- signal gets delivered to random thread). – C.M. Oct 26 '18 at 18:00

0 Answers0