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.1
Received 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