From 62d2ab3e687bfc7e0a02adedee30314b8ef1b08b Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 8 Feb 2009 16:11:26 +0000 Subject: [PATCH] Continue process if suspended. --- TODO | 2 -- client.c | 7 ++++++- server.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- tmux.c | 6 +++--- tmux.h | 6 ++++-- window.c | 6 ++---- 6 files changed, 62 insertions(+), 13 deletions(-) diff --git a/TODO b/TODO index b557f5d8..f3c2a92c 100644 --- a/TODO +++ b/TODO @@ -86,6 +86,4 @@ - 88 colour support; new grid cell flag, and 256<->88 88<->16 translation tables - some fix for SF feature request 2527847 - now remain-by-default has gone cannot control it per-session -- if the child is suspended in window with eg ^Z it should be restarted, or - ^Z should be ignored - clear window title on exit diff --git a/client.c b/client.c index 811d7567..dc15bdfa 100644 --- a/client.c +++ b/client.c @@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.42 2009-01-21 22:47:31 nicm Exp $ */ +/* $Id: client.c,v 1.43 2009-02-08 16:11:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -142,6 +143,10 @@ client_main(struct client_ctx *cctx) error = NULL; xtimeout = INFTIM; while (!sigterm) { + if (sigchld) { + waitpid(WAIT_ANY, NULL, WNOHANG); + sigchld = 0; + } if (sigwinch) client_handle_winch(cctx); if (sigcont) { diff --git a/server.c b/server.c index 02694d28..290ab8f0 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.116 2009-01-29 20:13:12 nicm Exp $ */ +/* $Id: server.c,v 1.117 2009-02-08 16:11:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ struct clients clients; int server_main(const char *, int); void server_shutdown(void); +void server_child_signal(void); void server_fill_windows(struct pollfd **); void server_handle_windows(struct pollfd **); void server_fill_clients(struct pollfd **); @@ -230,6 +232,12 @@ server_main(const char *srv_path, int srv_fd) if (sigterm) server_shutdown(); + /* Handle child exit. */ + if (sigchld) { + server_child_signal(); + sigchld = 0; + } + /* Initialise pollfd array. */ nfds = 1; for (i = 0; i < ARRAY_LENGTH(&windows); i++) { @@ -358,6 +366,44 @@ server_shutdown(void) server_write_client(c, MSG_SHUTDOWN, NULL, 0); } } + +/* Handle SIGCHLD. */ +void +server_child_signal(void) +{ + struct window *w; + struct window_pane *wp; + int status; + pid_t pid; + u_int i; + + for (;;) { + switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) { + case -1: + if (errno == ECHILD) + return; + fatal("waitpid"); + case 0: + return; + } + if (!WIFSTOPPED(status)) + continue; + if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU) + continue; + + for (i = 0; i < ARRAY_LENGTH(&windows); i++) { + w = ARRAY_ITEM(&windows, i); + if (w == NULL) + continue; + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp->pid == pid) { + if (killpg(pid, SIGCONT) != 0) + kill(pid, SIGCONT); + } + } + } + } +} /* Fill window pollfds. */ void diff --git a/tmux.c b/tmux.c index b0d15595..14b317c5 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.104 2009-01-30 00:24:49 nicm Exp $ */ +/* $Id: tmux.c,v 1.105 2009-02-08 16:11:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -17,7 +17,6 @@ */ #include -#include #include #include @@ -46,6 +45,7 @@ const char *_malloc_options = "AJX"; volatile sig_atomic_t sigwinch; volatile sig_atomic_t sigterm; volatile sig_atomic_t sigcont; +volatile sig_atomic_t sigchld; char *cfg_file; struct options global_options; @@ -103,7 +103,7 @@ sighandler(int sig) sigterm = 1; break; case SIGCHLD: - waitpid(WAIT_ANY, NULL, WNOHANG); + sigchld = 1; break; case SIGCONT: sigcont = 1; diff --git a/tmux.h b/tmux.h index 8f53d599..ddbd2e28 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.259 2009-02-03 17:21:19 tcunha Exp $ */ +/* $Id: tmux.h,v 1.260 2009-02-08 16:11:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -585,10 +585,12 @@ struct window_pane { int flags; #define PANE_HIDDEN 0x1 +#define PANE_RESTART 0x2 char *cmd; char *cwd; + pid_t pid; int fd; char tty[TTY_NAME_MAX]; struct buffer *in; @@ -610,7 +612,6 @@ TAILQ_HEAD(window_panes, window_pane); struct window { char *name; struct timeval name_timer; - pid_t pgrp; struct window_pane *active; struct window_panes panes; @@ -974,6 +975,7 @@ char *fgetln(FILE *, size_t *); extern volatile sig_atomic_t sigwinch; extern volatile sig_atomic_t sigterm; extern volatile sig_atomic_t sigcont; +extern volatile sig_atomic_t sigchld; extern struct options global_options; extern struct options global_window_options; extern char *cfg_file; diff --git a/window.c b/window.c index 2526289e..c8780e31 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.64 2009-01-28 19:52:21 nicm Exp $ */ +/* $Id: window.c,v 1.65 2009-02-08 16:11:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -213,7 +213,6 @@ window_create(const char *name, const char *cmd, const char *cwd, TAILQ_INIT(&w->panes); w->active = NULL; - w->pgrp = -1; w->sx = sx; w->sy = sy; @@ -562,14 +561,13 @@ window_pane_spawn(struct window_pane *wp, ws.ws_col = screen_size_x(&wp->base); ws.ws_row = screen_size_y(&wp->base); - wp->window->pgrp = -1; if (gettimeofday(&wp->window->name_timer, NULL) != 0) fatal("gettimeofday"); tv.tv_sec = 0; tv.tv_usec = NAME_INTERVAL * 1000L; timeradd(&wp->window->name_timer, &tv, &wp->window->name_timer); - switch (forkpty(&wp->fd, wp->tty, NULL, &ws)) { + switch (wp->pid = forkpty(&wp->fd, wp->tty, NULL, &ws)) { case -1: wp->fd = -1; xasprintf(cause, "%s: %s", cmd, strerror(errno));