diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-01-11 19:57:31 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-01-21 15:00:25 +0000 |
commit | ca18baf83a6b9f1ac05fbdbf448517a4b4015768 (patch) | |
tree | 6c651b735ce3bf6a8fbb44dd4580c3589dff389a /dbus | |
parent | c894f62f2c33cd984805ec069ad3ca8684cbafe1 (diff) | |
download | dbus-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.c | 27 |
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; } |