How To Repeatedly Restart A Program Via Signal
I wanted a convenient way to restart a program. I thought I could just catch a signal (USR1 in the example) and call exec.
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
char* const* args;
void restart() {
printf("restarting\n");
execv(args[0], args);
}
int main(int argc, char* const argv[]) {
printf("Starting\n");
args = argv;
signal(SIGUSR1, restart);
raise(SIGUSR1); // could use pkill -SIGUSR1 file-name instead
pause();
printf("Terminated normally\n");
return 0;
}
The above example kinda works. The output is
Starting
restarting
Starting
and then it hangs. Other signals can still be received.
I assume I'm just failing to clear the signal. The expected behavior is for program to keep restarting indefinitely.
Answer
Linux's man 2 signal
explains what happens when you set a signal handler with signal
. There are two possibilities:
- The disposition of the signal is reset to
SIG_DFL
, and then the handler is called. To handle this signal again, you need to re-establish the signal handler. This would have worked as you expected.
Or:
- The signal is blocked, and then the handler is called. When the handler returns, the signal is unblocked. If the handler doesn't return, the signal is still blocked, which is what was happening to you.
So one works with your code and the other doesn't. But which of the two applies? There is no reliable way of knowing. Posix allows both possibilities and both possibilities exist on different platforms. For this reason, the Linux manpage recommends:
The only portable use of signal() is to set a signal's disposition to
SIG_DFL
orSIG_IGN
... [D]o not use it for [the purpose of establishing a signal handler].POSIX.1 solved the portability mess by specifying
sigaction(2)
, whichprovides explicit control of the semantics when a signal handler is invoked; use that interface instead ofsignal()
.
That's good advice. When you change to using sigaction
, you'll probably want to go for the first option above, which requires:
sa.sa_flags = SA_RESETHAND | SA_NODEFER
That also comes from the Linux manpage, which is well worth reading in full. (Of course, the sigaction
manpage is even more relevant.)
Related Questions
- → OctoberCMS Backend Loging Hash Error
- → "failed to open stream" error when executing "migrate:make"
- → OctoberCMS - How to make collapsible list default to active only on non-mobile
- → Create plugin that makes objects from model in back-end
- → October CMS Plugin Routes.php not registering
- → OctoberCMS Migrate Table
- → How to install console for plugin development in October CMS
- → OctoberCMS Rain User plugin not working or redirecting
- → October CMS Custom Mail Layout
- → October CMS - How to correctly route
- → October CMS create a multi select Form field
- → How to update data attribute on Ajax complete
- → October CMS - Conditionally Load a Different Page