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 <[EMAIL PROTECTED]>
---
 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.1


Reply via email to