diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h index f28e5580f..a253e0d73 100644 --- a/compel/include/uapi/infect.h +++ b/compel/include/uapi/infect.h @@ -111,6 +111,7 @@ struct infect_ctx { unsigned long flags; /* fine-tune (e.g. faults) */ void (*child_handler)(int, siginfo_t *, void *); /* hander for SIGCHLD deaths */ + struct sigaction orig_handler; open_proc_fn open_proc; diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 2be67f12a..942cef877 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -384,16 +384,9 @@ static int setup_child_handler(struct parasite_ctl *ctl) return 0; } -static int restore_child_handler() +static int restore_child_handler(struct parasite_ctl *ctl) { - struct sigaction sa = { - .sa_handler = SIG_DFL, /* XXX -- should be original? */ - .sa_flags = SA_SIGINFO | SA_RESTART, - }; - - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGCHLD); - if (sigaction(SIGCHLD, &sa, NULL)) { + if (sigaction(SIGCHLD, &ctl->ictx.orig_handler, NULL)) { pr_perror("Unable to setup SIGCHLD handler"); return -1; } @@ -1007,6 +1000,14 @@ static int simple_open_proc(int pid, int mode, const char *fmt, ...) return open(path, mode); } +static void handle_sigchld(int signal, siginfo_t *siginfo, void *data) +{ + int status; + + waitpid(-1, &status, WNOHANG); + /* FIXME -- what to do here? */ +} + struct parasite_ctl *compel_prepare(int pid) { struct parasite_ctl *ctl; @@ -1020,6 +1021,9 @@ struct parasite_ctl *compel_prepare(int pid) ictx->task_size = compel_task_size(); ictx->open_proc = simple_open_proc; ictx->syscall_ip = find_executable_area(pid); + ictx->child_handler = handle_sigchld; + sigaction(SIGCHLD, NULL, &ictx->orig_handler); + if (ictx->syscall_ip == (unsigned long)MAP_FAILED) goto err; ictx->sock = make_sock_for(pid); @@ -1049,7 +1053,7 @@ static int parasite_fini_seized(struct parasite_ctl *ctl) enum trace_flags flag; /* stop getting chld from parasite -- we're about to step-by-step it */ - if (restore_child_handler()) + if (restore_child_handler(ctl)) return -1; /* Start to trace syscalls for each thread */ diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c index dc510ba66..8002546f9 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -581,6 +581,10 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ictx->open_proc = do_open_proc; ictx->child_handler = sigchld_handler; + ictx->orig_handler.sa_handler = SIG_DFL; + ictx->orig_handler.sa_flags = SA_SIGINFO | SA_RESTART; + sigemptyset(&ictx->orig_handler.sa_mask); + sigaddset(&ictx->orig_handler.sa_mask, SIGCHLD); ictx->sock = dmpi(item)->netns->net.seqsk; ictx->save_regs = save_task_regs; ictx->make_sigframe = make_sigframe;