diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2017-05-04 21:39:43 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2017-05-04 21:39:13 +0200 |
| commit | d9d8e81b39a77c198d344d096be55e9cd8cdd4e9 (patch) | |
| tree | 99f2e0ef0dae8ee3545ba2297c9f88e739195869 /vis.c | |
| parent | 71eab6d5d72145f17ab3d4c87945ac12176ae8e9 (diff) | |
| download | vis-d9d8e81b39a77c198d344d096be55e9cd8cdd4e9.tar.gz vis-d9d8e81b39a77c198d344d096be55e9cd8cdd4e9.tar.xz | |
vis: improve job control for forked process
We need to unblock SIGTERM for the child process. Also we should
deliver signals to the correct process group. This is still fragile
and will need to be rewritten when we finally introduce a global
event loop.
Diffstat (limited to 'vis.c')
| -rw-r--r-- | vis.c | 29 |
1 files changed, 27 insertions, 2 deletions
@@ -1702,11 +1702,20 @@ int vis_pipe(Vis *vis, File *file, Filerange *range, const char *argv[], vis_info_show(vis, "fork failure: %s", strerror(errno)); return -1; } else if (pid == 0) { /* child i.e filter */ + sigset_t sigterm_mask; + sigemptyset(&sigterm_mask); + sigaddset(&sigterm_mask, SIGTERM); + if (sigprocmask(SIG_UNBLOCK, &sigterm_mask, NULL) == -1) { + fprintf(stderr, "failed to reset signal mask"); + exit(EXIT_FAILURE); + } + int null = open("/dev/null", O_WRONLY); if (null == -1) { fprintf(stderr, "failed to open /dev/null"); exit(EXIT_FAILURE); } + if (!interactive) dup2(pin[0], STDIN_FILENO); close(pin[0]); @@ -1757,7 +1766,7 @@ int vis_pipe(Vis *vis, File *file, Filerange *range, const char *argv[], do { if (vis->interrupted) { - kill(-pid, SIGTERM); + kill(0, SIGTERM); break; } @@ -1838,8 +1847,24 @@ err: if (perr[0] != -1) close(perr[0]); - for (pid_t died; (died = waitpid(pid, &status, 0)) != -1 && pid != died;); + for (;;) { + if (vis->interrupted) + kill(0, SIGTERM); + pid_t died = waitpid(pid, &status, 0); + if ((died == -1 && errno == ECHILD) || pid == died) + break; + } + + /* clear any pending SIGTERM */ + struct sigaction sigterm_ignore, sigterm_old; + sigterm_ignore.sa_handler = SIG_IGN; + sigterm_ignore.sa_flags = 0; + sigemptyset(&sigterm_ignore.sa_mask); + sigaction(SIGTERM, &sigterm_ignore, &sigterm_old); + sigaction(SIGTERM, &sigterm_old, NULL); + + vis->interrupted = false; vis->ui->terminal_restore(vis->ui); return status; |
