summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>2014-08-27 13:31:26 +0300
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>2014-08-28 10:15:46 +0300
commit23ade621e7cd5ad6b7c08eddbf9f799cd921e2a9 (patch)
treed6b37e74e838424aa2e9a18088690732456ccee6
parent826dc14ec43b92d992d8cf73cfdfde132c3f814f (diff)
downloadweston-23ade621e7cd5ad6b7c08eddbf9f799cd921e2a9.tar.gz
weston-23ade621e7cd5ad6b7c08eddbf9f799cd921e2a9.tar.bz2
weston-23ade621e7cd5ad6b7c08eddbf9f799cd921e2a9.zip
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 <stu_dby@126.com> Cc: Derek Foreman <derekf@osg.samsung.com> Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
-rw-r--r--src/compositor.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/src/compositor.c b/src/compositor.c
index c62077c4..8705950e 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -46,6 +46,7 @@
#include <setjmp.h>
#include <sys/time.h>
#include <time.h>
+#include <errno.h>
#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;
}