如何让子进程自己处理SIGSEGV
How to make the child process handle SIGSEGV by itself
我有一个程序调用 run
来做某事。
在 run
运行ning 中,它将生成一个 SIGSEGV 并通过 sigsetjmp/siglongjmp.
捕获此信号和正常 return
但是,如果我为 运行 函数 run
创建多个子进程,run
似乎无法捕捉到它自己的 SIGSEGV 信号。
因此,我的问题是子进程如何正常捕获自己的SIGSEGV和return?
在这里,我的示例代码。
struct sigaction act, oact;
static sigjmp_buf jmpbuf;
int run(void * arg);
static void sig_handle(int signum, siginfo_t* siginfo, void* context){
siglongjmp(jmpbuf,1);
}
#define STACK_SIZE (1024 * 1024)
int main()
{
pid_t pid;
pid_t pid1;
char *stack;
char *stackTop;
stack = (char*)malloc(STACK_SIZE);
if (stack == NULL){
fprintf(stderr,"malloc failed\n");
exit(-1);
}
stackTop = stack+STACK_SIZE;
pid = clone(run, stackTop, CLONE_VM|SIGCHLD, (void*)2);
if (pid == -1){
fprintf(stderr,"clone failed\n");
exit(-1);
}
for(int i = 0; i < 3; ++i)
run((void *)i);
if (waitpid(pid, NULL, 0) == -1){ /* Wait for child */
fprintf(stderr,"clone close failed\n");
exit(-1);
}
return 0;
}
int run(void * arg){
act.sa_sigaction = sig_handle;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(sigaction(SIGSEGV, &act, &oact)<0)
exit(-1);
int args = (uint64_t)arg;
if(sigsetjmp(jmpbuf,1)==0){
if(args==2)
sleep(1);
*(uint64_t *)0 = 1;
}else
sleep(1);
return 0;
}
However, if i create multiple child processes
您正在使用的clone()
函数不会创建子进程,它会在当前进程中创建线程,所有共享 地址 space 与父级(CLONE_VM
标志)。
虽然这可以起作用,但要正确地做到这一点非常棘手,而且很可能你做不到。特别是,您不能在 clone()
d 进程中调用 any libc 函数(并且您确实调用了 sigaction()
;这是禁忌)。
如果多个线程共享,您也不能使用单个 jmpbuf
。
简单的解决方案是 实际上 创建子进程(使用 fork()
)。
我有一个程序调用 run
来做某事。
在 run
运行ning 中,它将生成一个 SIGSEGV 并通过 sigsetjmp/siglongjmp.
捕获此信号和正常 return
但是,如果我为 运行 函数 run
创建多个子进程,run
似乎无法捕捉到它自己的 SIGSEGV 信号。
因此,我的问题是子进程如何正常捕获自己的SIGSEGV和return?
在这里,我的示例代码。
struct sigaction act, oact;
static sigjmp_buf jmpbuf;
int run(void * arg);
static void sig_handle(int signum, siginfo_t* siginfo, void* context){
siglongjmp(jmpbuf,1);
}
#define STACK_SIZE (1024 * 1024)
int main()
{
pid_t pid;
pid_t pid1;
char *stack;
char *stackTop;
stack = (char*)malloc(STACK_SIZE);
if (stack == NULL){
fprintf(stderr,"malloc failed\n");
exit(-1);
}
stackTop = stack+STACK_SIZE;
pid = clone(run, stackTop, CLONE_VM|SIGCHLD, (void*)2);
if (pid == -1){
fprintf(stderr,"clone failed\n");
exit(-1);
}
for(int i = 0; i < 3; ++i)
run((void *)i);
if (waitpid(pid, NULL, 0) == -1){ /* Wait for child */
fprintf(stderr,"clone close failed\n");
exit(-1);
}
return 0;
}
int run(void * arg){
act.sa_sigaction = sig_handle;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(sigaction(SIGSEGV, &act, &oact)<0)
exit(-1);
int args = (uint64_t)arg;
if(sigsetjmp(jmpbuf,1)==0){
if(args==2)
sleep(1);
*(uint64_t *)0 = 1;
}else
sleep(1);
return 0;
}
However, if i create multiple child processes
您正在使用的clone()
函数不会创建子进程,它会在当前进程中创建线程,所有共享 地址 space 与父级(CLONE_VM
标志)。
虽然这可以起作用,但要正确地做到这一点非常棘手,而且很可能你做不到。特别是,您不能在 clone()
d 进程中调用 any libc 函数(并且您确实调用了 sigaction()
;这是禁忌)。
如果多个线程共享,您也不能使用单个 jmpbuf
。
简单的解决方案是 实际上 创建子进程(使用 fork()
)。