Самостоятельно перезапустить программу на segfault под Linux
В Linux, что было бы лучшим способом перезапустить программу в случае сбоя, перехватив исключение в обработчике сбоя (например, в segfault)?
7 ответов
Вы можете иметь цикл, в котором вы по существу fork()
, сделайте реальную работу с ребенком, и просто подождите ребенка и проверьте его статус выхода в родительском. Вы также можете использовать систему, которая аналогичным образом отслеживает и перезапускает программы, такие как daemontools, runit и т. Д.
Самое простое
while [ 1 ]; do ./program && break; done
в основном, вы запускаете программу до тех пор, пока она не вернет 0, а затем вы ломаете
SIGSEGV
можно поймать (см. man 3 signal
или же man 2 sigaction
), и программа может вызвать один из exec
семейство функции на себя, чтобы перезапустить. Аналогично для большинства сбоев во время выполнения (SIGFPE
, SIGILL
, SIGBUS
, SIGSYS
...)
Я бы немного подумал, прежде чем делать это. Это довольно необычная стратегия для Unix-программ, и вы можете удивить своих пользователей (не обязательно приятным способом).
В любом случае, не включайте автозапуск SIGTERM
если есть какие-то ресурсы, которые вы хотите очистить перед смертью, в противном случае злые пользователи будут использовать SIGKILL
и ты оставишь беспорядок.
В качестве дополнения к тому, что было предложено здесь:
Другой вариант - сделать так, как это делается для демона getty. Пожалуйста, смотрите /etc/inittab и соответствующую справочную страницу inittab(5). Кажется, это самое общесистемное средство;-).
Это может выглядеть как фрагмент файла ниже. Очевидное преимущество - это стандартное средство, позволяющее управлять демоном через уровни выполнения.
# 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
Процессы не могут перезапустить себя, но вы можете использовать утилиту, например crontab(1)
запланировать сценарий, чтобы проверить, если процесс все еще жив через регулярные промежутки времени.
Попробуйте следующий код, если он относится к segfault. Это может быть изменено по мере необходимости.
#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)
}
Сама программа явно не должна проверять, запущена она или нет:)
Большинство корпоративных решений на самом деле - просто причудливые способы получения результатов от ps()
для заданной строки и выполнение действия в случае, если определенные критерии удовлетворены - то есть, если ваш процесс не найден, вызовите стартовый скрипт.