Self restart program on segfault under Linux
Under Linux what would be the best way开发者_如何学Go for a program to restart itself on a crash by catching the exception in a crashhandler (for example on a segfault)?
simplest is
while [ 1 ]; do ./program && break; done
basically, you run program until it is return 0, then you break.
You can have a loop in which you essentially fork()
, do the real work in the child, and just wait on the child and check its exit status in the parent. You can also use a system which monitors and restarts programs in a similar fashion, such as daemontools, runit, etc.
SIGSEGV
can be caught (see man 3 signal
or man 2 sigaction
), and the program can call one of the exec
family of function on itself in order to restart. Similarly for most runtime crashes (SIGFPE
, SIGILL
, SIGBUS
, SIGSYS
, ...).
I'd think a bit before doing this, though. It is a rather unusual strategy for a unix program, and you may surprise your users (not necessarily in a pleasant way, either).
In any case, be sure to not auto-restart on SIGTERM
if there are any resources you want to clean up before dying, otherwise angry users will use SIGKILL
and you'll leave a mess.
As a complement to what was proposed here:
Another option is to do like it is done for getty daemon. Please see /etc/inittab and appropriate inittab(5) man page. It seems it is most system-wide mean ;-).
It could look like file fragment below. Obvious advantage this mean is pretty standard and it allows to control your daemon through run levels.
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
Processes can't restart themselves, but you could use a utility like crontab(1)
to schedule a script to check if the process is still alive at regular intervals.
The program itself obviously shouldn't check whether it is running or not running :)
Most enterprise solutions are actually just fancy ways of grepping the output from ps()
for a given string, and performing an action in the event that certain criteria are satisfied - i.e. if your process is not found, then call the start script.
Try the following code if its specific to segfault. This can be modified as required.
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <poll.h>
sigjmp_buf buf;
void handler(int sig) {
siglongjmp(buf, 1);
}
int main() {
//signal(SIGINT, handler);
//register all signals
struct sigaction new_action, old_action;
new_action.sa_handler = handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGSEGV, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGSEGV, &new_action, NULL);
if (!sigsetjmp(buf, 1)){
printf("starting\n");
//code or function/method here
}
else{
printf("restarting\n");
//code or function/method here
}
while(1) {
poll(NULL,0,100); //ideally use usleep or nanosleep. for now using poll() as a timer
printf("processing...\n");
}
return 0; //or exit(SUCESS)
}
精彩评论