From 23ade621e7cd5ad6b7c08eddbf9f799cd921e2a9 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Wed, 27 Aug 2014 13:31:26 +0300 Subject: [PATCH] compositor: leave no zombie behind When SIGCHLD fires, we may have more than one zombie to be collected. Run waitpid() in a loop until no more zombies are found, and clean them all up. It looks like the SIGCHLD signalfd does not trigger again for remaining zombies, so we need the loop. This works around a crash in text_backend_notified_destroy, which ends up using stale input_method.client if the sigchld handler is not called. The crash could be triggered by removing both weston-desktop-shell and weston-keyboard, so that both would try to respawn and give up, and then quitting Weston. Cc: rawoul@gmail.com Cc: Boyan Ding Cc: Derek Foreman Signed-off-by: Pekka Paalanen Reviewed-by: Derek Foreman --- src/compositor.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/compositor.c b/src/compositor.c index c62077c..8705950 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef HAVE_LIBUNWIND #define UNW_LOCAL_ONLY @@ -68,22 +69,23 @@ sigchld_handler(int signal_number, void *data) int status; pid_t pid; - pid = waitpid(-1, &status, WNOHANG); - if (!pid) - return 1; + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + wl_list_for_each(p, &child_process_list, link) { + if (p->pid == pid) + break; + } - wl_list_for_each(p, &child_process_list, link) { - if (p->pid == pid) - break; - } + if (&p->link == &child_process_list) { + weston_log("unknown child process exited\n"); + continue; + } - if (&p->link == &child_process_list) { - weston_log("unknown child process exited\n"); - return 1; + wl_list_remove(&p->link); + p->cleanup(p, status); } - wl_list_remove(&p->link); - p->cleanup(p, status); + if (pid < 0 && errno != ECHILD) + weston_log("waitpid error %m\n"); return 1; } -- 2.7.4