如何让子进程自己处理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())。