I have a program that calls run
to do something.
In run
running, which will generate a SIGSEGV and catch this signal and normal return by sigsetjmp/siglongjmp.
However, if i create multiple child processes to run the function run
, the run
seems to be unable to catch its own SIGSEGV signal.
Therefore, my question is how does the child process capture its own SIGSEGV and return normally?
Here, my example code.
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
The clone()
function you are using does not create child processes, it creates threads within the current process, all sharing the address space with the parent (CLONE_VM
flag).
While this can be made to work, it's extremely tricky to do this correctly, and there is a high chance that you aren't. In particular, you can not call any libc function within the clone()
d process (and you do call sigaction()
; that's a no-no).
You also can't use a single jmpbuf
if it is shared by multiple threads.
The simple solution is to actually create child processes (using fork()
).