Ask waitpid() for all zombies in sigchld_handler and put them in a list for later
destroying. The previous implementation might have lead to zombies when
processes were dying fast.
Signed-off-by: Rainer Müller <raimue_AT_codingfarm.de>
--- dvtm.c | 52 +++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 43 insertions(+), 9 deletions(-) diff --git a/dvtm.c b/dvtm.c index 17ac4a4..6a23ad1 100644 --- a/dvtm.c +++ b/dvtm.c @@ -52,6 +52,12 @@ struct Client { Client *prev; }; +typedef struct ClientList ClientList; +struct ClientList { + Client *client; + ClientList *next; +}; + #define ALT(k) ((k) + (161 - 'a')) #ifndef CTRL #define CTRL(k) ((k) & 0x1F) @@ -134,7 +140,7 @@ Client *sel = NULL; Client *msel = NULL; double mwfact = MWFACT; Layout *layout = layouts; -Client *client_killed = NULL; +ClientList *kill_list = NULL; int statusfd = -1; char stext[512]; int barpos = BARPOS; @@ -598,6 +604,21 @@ create(const char *args[]){ void destroy(Client *c){ + ClientList *cl; + cl = malloc(sizeof(ClientList)); + cl->client = c; + cl->next = NULL; + + if (kill_list == NULL) { + kill_list = cl; + } else { + cl->next = kill_list; + kill_list = cl; + } +} + +void +destroy_really(Client *c){ if(sel == c) focusnextnm(NULL); detach(c); @@ -761,12 +782,23 @@ get_client_by_pid(pid_t pid){ void sigchld_handler(int sig){ int errsv = errno; + int status; + pid_t pid; - int child_status; signal(SIGCHLD, sigchld_handler); - pid_t pid = wait(&child_status); - debug("child with pid %d died\n", pid); - client_killed = get_client_by_pid(pid); + + while ((pid = waitpid(-1, &status, WNOHANG)) != 0) { + if (pid == -1) { + if (errno == ECHILD) { + /* no more child processes */ + break; + } + eprint("waitpid: %s\n", strerror(errno)); + break; + } + debug("child with pid %d died\n", pid); + destroy(get_client_by_pid(pid)); + } errno = errsv; } @@ -927,9 +959,11 @@ main(int argc, char *argv[]) { if(need_screen_resize) resize_screen(); - if(client_killed){ - destroy(client_killed); - client_killed = NULL; + while(kill_list) { + ClientList *cl = kill_list; + destroy_really(cl->client); + kill_list = cl->next; + free(cl); } FD_ZERO(&rd); @@ -1025,7 +1059,7 @@ main(int argc, char *argv[]) { if(FD_ISSET(c->pty, &rd)){ if (madtty_process(c->term) < 0 && errno == EIO) { /* client probably terminated */ - client_killed = c; + destroy(c); } if(c != sel){ draw_content(c); -- 1.5.5.1Received on Wed Apr 30 2008 - 00:11:15 UTC
This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 15:36:42 UTC