summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw@src.gnome.org>2018-08-19 11:30:44 +0800
committerTing-Wei Lan <lantw@src.gnome.org>2018-08-19 12:40:55 +0800
commit54d4c767d5793b54e064836111e4e08227eca52a (patch)
tree4e0292c14133de8c32aa35131f797586cf78653e
parentf876f4174fe87925fe2199998e7f5048f1bfe87c (diff)
downloadglib-wip/lantw/fix-gtestdbus-crash-on-freebsd.tar.gz
gtestdbus: Fix watcher crash on FreeBSDwip/lantw/fix-gtestdbus-crash-on-freebsd
In file gio/gtestdbus.c, function watch_parent, there is a loop which waits for commands sent from the parent process and kills all processes recorded in 'pids_to_kill' array on parent process exit. The detection of parent process exit is done by calling g_poll and checking whether the returned event is G_IO_HUP. However, 'revents' is a bit mask, and we should use a bitwise-AND check instead of the equality check here. It seems to work fine on Linux, but it fails on FreeBSD because the g_poll returns both G_IO_IN and G_IO_HUP on pipe close. This means the watcher process continues waiting for commands after the parent process exit, and g_io_channel_read_line returns G_IO_STATUS_EOF with 'command' set to NULL. Then the watcher process crashes with segfault when calling sscanf because 'command' is NULL. Since the test result is already reported by the parent process as 'OK', this kind of crash is likely to be unnoticed unless someone checks dmesg messages after the test: pid 57611 (defaultvalue), uid 1001: exited on signal 11 pid 57935 (actions), uid 1001: exited on signal 11 pid 57945 (gdbus-bz627724), uid 1001: exited on signal 11 pid 57952 (gdbus-connection), uid 1001: exited on signal 11 pid 57970 (gdbus-connection-lo), uid 1001: exited on signal 11 pid 57976 (gdbus-connection-sl), uid 1001: exited on signal 11 pid 58039 (gdbus-exit-on-close), uid 1001: exited on signal 11 pid 58043 (gdbus-exit-on-close), uid 1001: exited on signal 11 pid 58047 (gdbus-exit-on-close), uid 1001: exited on signal 11 pid 58051 (gdbus-exit-on-close), uid 1001: exited on signal 11 pid 58055 (gdbus-export), uid 1001: exited on signal 11 pid 58059 (gdbus-introspection), uid 1001: exited on signal 11 pid 58065 (gdbus-names), uid 1001: exited on signal 11 pid 58071 (gdbus-proxy), uid 1001: exited on signal 11 pid 58079 (gdbus-proxy-threads), uid 1001: exited on signal 11 pid 58083 (gdbus-proxy-well-kn), uid 1001: exited on signal 11 pid 58091 (gdbus-test-codegen), uid 1001: exited on signal 11 pid 58095 (gdbus-threading), uid 1001: exited on signal 11 pid 58104 (gmenumodel), uid 1001: exited on signal 11 pid 58108 (gnotification), uid 1001: exited on signal 11 pid 58112 (gdbus-test-codegen-), uid 1001: exited on signal 11 pid 58116 (gapplication), uid 1001: exited on signal 11 pid 58132 (dbus-appinfo), uid 1001: exited on signal 11 If the watcher process crashes before killing the dbus-daemon process spawned by the parent process, the dbus-daemon process will keep running after all tests complete. Due to the implementation of 'communicate' function in Python subprocess, it causes meson to crash. 'communicate' assumes the stdout and stderr pipes are closed when the child process exits, but it is not true if processes forked by the child process doesn't exit. It causes Python subprocess 'communicate' function to block on the call to poll until the timeout expires even if the test finishes in a few seconds. Meson assumes the timeout exception always means the test is still running. It calls 'communicate' again and crashes because pipes no longer exist. https://gitlab.gnome.org/Infrastructure/GitLab/issues/286 https://github.com/mesonbuild/meson/issues/3967 https://bugs.python.org/issue30154
-rw-r--r--gio/gtestdbus.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/gio/gtestdbus.c b/gio/gtestdbus.c
index 685503c5e..2fc2d51f5 100644
--- a/gio/gtestdbus.c
+++ b/gio/gtestdbus.c
@@ -179,7 +179,7 @@ watch_parent (gint fd)
if (num_events == 0)
continue;
- if (fds[0].revents == G_IO_HUP)
+ if (fds[0].revents & G_IO_HUP)
{
/* Parent quit, cleanup the mess and exit */
for (n = 0; n < pids_to_kill->len; n++)