Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux下segfault的自重启程序_C_Linux_Restart_Segmentation Fault_Recover - Fatal编程技术网

C Linux下segfault的自重启程序

C Linux下segfault的自重启程序,c,linux,restart,segmentation-fault,recover,C,Linux,Restart,Segmentation Fault,Recover,在Linux下,通过捕获崩溃处理器中的异常(例如在segfault上),程序在崩溃时重新启动自己的最佳方式是什么?进程无法自行重新启动,但您可以使用类似于调度脚本的实用工具定期检查进程是否仍处于活动状态。最简单的方法是 while [ 1 ]; do ./program && break; done 基本上,您运行程序直到它返回0,然后中断。您可以有一个循环,在这个循环中,您基本上是fork(),在子进程中执行真正的工作,然后等待子进程并在父进程中检查其退出状态。您还可以使用以

在Linux下,通过捕获崩溃处理器中的异常(例如在segfault上),程序在崩溃时重新启动自己的最佳方式是什么?

进程无法自行重新启动,但您可以使用类似于调度脚本的实用工具定期检查进程是否仍处于活动状态。

最简单的方法是

while [ 1 ]; do ./program && break; done

基本上,您运行程序直到它返回0,然后中断。

您可以有一个循环,在这个循环中,您基本上是
fork()
,在子进程中执行真正的工作,然后等待子进程并在父进程中检查其退出状态。您还可以使用以类似方式监视和重新启动程序的系统,如daemontools、runit等。

程序本身显然不应该检查它是否正在运行:)


实际上,大多数企业解决方案只是对给定字符串的
ps()
输出进行灰色化处理,并在满足某些条件的情况下执行操作的奇特方式,即如果找不到流程,则调用开始脚本。

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

如果特定于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)
}
#包括
#包括
#包括
#包括
sigjmp_buf buf;
无效处理程序(int sig){
siglongjmp(buf,1);
} 
int main(){
//信号(SIGINT,handler);
//登记所有信号
结构sigaction新动作、旧动作;
new_action.sa_handler=handler;
SIGEPTYSET(和新的_action.sa_mask);
新建_action.sa_标志=0;
sigaction(SIGSEGV、NULL和old_action);
if(旧的\u action.sa\u处理程序!=SIG\u IGN)
sigaction(SIGSEGV和new_action,NULL);
如果(!sigsetjmp(buf,1)){
printf(“启动\n”);
//此处的代码或函数/方法
}
否则{
printf(“重新启动”);
//此处的代码或函数/方法
}
而(1){
poll(NULL,0100);//理想情况下使用usleep或nanosleep。目前使用poll()作为计时器
printf(“处理…\n”);
}
返回0;//或退出(成功)
}

没有任何东西阻止程序调用
argv[0]
上的
exec
(几乎总是它自己的可执行文件).“崩溃”是操作系统发送信号(默认行为为“终止进程”)。默认行为可以替换为用户定义的函数…如果内存损坏,导致SEGV处理程序中出现第二个SEGV,该怎么办?从本质上讲,从另一个进程运行更可靠。我同意@dmckee,AFAIK调用exec基本上是另一个具有相同PID的进程。这是一次重生,所有内存都会丢失(不确定共享内存和类似资源是否存在任何需要显式清理的问题)[只要复制argv[0]的内存是干净的,就应该是好的]@dmckee如何替换默认行为?可以从程序内部完成吗?我的意思是,一个程序可能会发现自己崩溃,然后重新启动。这种解决方案会使故意终止进程变得困难(至少用户最了解发生了什么…)。这可能是好的,也可能是坏的,取决于预期用途。@dmc当然,最简单的并不一定是好的。在不了解更多需求的情况下很难说。我喜欢你的答案,因为它更有力。哦,我不是在抱怨。它的优点是非常简单,有时你不想让无知的用户把它杀掉…@dmckee-具有这样的属性:家长可以捕获
SIGTERM
,给孩子发信号,等待,然后有序退出。这个答案应该也适用于这样做——bash的作业控制应该足够丰富以支持它。@dmckee I在重新启动之前添加了一个
sleep 2
,这样第二个Ctrl+C将停止无限循环。这是正确的方法。这不是一个好主意,从信号手册页:“根据POSIX的说法,在忽略不是由kill(2)或raise(3)生成的SIGFPE、SIGILL或SIGSEGV信号后,进程的行为是未定义的。”@Paul:我以前没有注意到这一点。我不清楚的是,在某个静态变量上运行一个调用exec的处理程序,而您已经将argv[0]复制到该静态变量中构成“忽视”“信号。我本能地认为它不是。在任何情况下,我都能够在Mac OS和linux上可靠地处理SIGSEGV。我不记得处理过SIGFPE,我也不认为我已经生成了所有的SIGILL或SIGBUS。当然,这里的其他建议是好的,并且实现了老年退休金计划的愿望,但是我把标题照字面理解了。请检查这里的一些答案