summaryrefslogtreecommitdiff
path: root/dbus
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2011-01-11 19:57:31 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2011-01-21 15:00:25 +0000
commitca18baf83a6b9f1ac05fbdbf448517a4b4015768 (patch)
tree6c651b735ce3bf6a8fbb44dd4580c3589dff389a /dbus
parentc894f62f2c33cd984805ec069ad3ca8684cbafe1 (diff)
downloaddbus-ca18baf83a6b9f1ac05fbdbf448517a4b4015768.tar.gz
dbus-spawn: don't leave bad file descriptors being watched
The code called from handle_watch() might close either or both of the sockets we're watching, without cleaning up the DBusWatch. This results in invalid file descriptors being passed to _dbus_poll(), which could end up busy-looping on a POLLNVAL condition until the babysitter loses its last ref (which automatically clears up both watches). Bug: https://bugs.freedesktop.org/show_bug.cgi?id=32992 Bug-NB: NB#200248 Reviewed-by: Colin Walters <walters@verbum.org>
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-spawn.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c
index dcd111d9..a1bab3df 100644
--- a/dbus/dbus-spawn.c
+++ b/dbus/dbus-spawn.c
@@ -774,7 +774,32 @@ handle_watch (DBusWatch *watch,
while (LIVE_CHILDREN (sitter) &&
babysitter_iteration (sitter, FALSE))
;
-
+
+ /* Those might have closed the sockets we're watching. Before returning
+ * to the main loop, we must sort that out. */
+
+ if (sitter->error_watch != NULL && sitter->error_pipe_from_child == -1)
+ {
+ _dbus_watch_invalidate (sitter->error_watch);
+
+ if (sitter->watches != NULL)
+ _dbus_watch_list_remove_watch (sitter->watches, sitter->error_watch);
+
+ _dbus_watch_unref (sitter->error_watch);
+ sitter->error_watch = NULL;
+ }
+
+ if (sitter->sitter_watch != NULL && sitter->socket_to_babysitter == -1)
+ {
+ _dbus_watch_invalidate (sitter->sitter_watch);
+
+ if (sitter->watches != NULL)
+ _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
+
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+ }
+
return TRUE;
}