Commit 0c03b505 authored by Simon McVittie's avatar Simon McVittie

_dbus_server_new_for_socket: Properly disconnect during error unwinding

_dbus_server_finalize_base() asserts that the socket has been
disconnected, but in some OOM code paths we would call it without
officially disconnecting. Do so.

This means we need to be a bit more careful about what is
socket_disconnect()'s responsibility to clean up, what is
_dbus_server_new_for_socket()'s responsibility, and what is the caller's
responsibility.
Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
Reviewed-by: Philip Withnall's avatarPhilip Withnall <withnall@endlessm.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89104
parent 1ce34bee
......@@ -96,6 +96,7 @@ dbus_bool_t _dbus_server_init_base (DBusServer *server,
const DBusString *address,
DBusError *error);
void _dbus_server_finalize_base (DBusServer *server);
void _dbus_server_disconnect_unlocked (DBusServer *server);
dbus_bool_t _dbus_server_add_watch (DBusServer *server,
DBusWatch *watch);
void _dbus_server_remove_watch (DBusServer *server,
......
......@@ -241,8 +241,11 @@ socket_disconnect (DBusServer *server)
socket_server->watch[i] = NULL;
}
_dbus_close_socket (socket_server->fds[i], NULL);
_dbus_socket_invalidate (&socket_server->fds[i]);
if (_dbus_socket_is_valid (socket_server->fds[i]))
{
_dbus_close_socket (socket_server->fds[i], NULL);
_dbus_socket_invalidate (&socket_server->fds[i]);
}
}
if (socket_server->socket_name != NULL)
......@@ -336,10 +339,24 @@ _dbus_server_new_for_socket (DBusSocket *fds,
socket_server->watch[i]))
{
int j;
for (j = 0 ; j < i ; j++)
_dbus_server_remove_watch (server,
socket_server->watch[j]);
/* The caller is still responsible for closing the fds until
* we return successfully, so don't let socket_disconnect()
* close them */
for (j = 0; j < n_fds; j++)
_dbus_socket_invalidate (&socket_server->fds[i]);
/* socket_disconnect() will try to remove all the watches;
* make sure it doesn't see the ones that weren't even added
* yet */
for (j = i; j < n_fds; j++)
{
_dbus_watch_invalidate (socket_server->watch[i]);
_dbus_watch_unref (socket_server->watch[i]);
socket_server->watch[i] = NULL;
}
_dbus_server_disconnect_unlocked (server);
SERVER_UNLOCK (server);
_dbus_server_finalize_base (&socket_server->base);
goto failed_2;
......
......@@ -764,6 +764,20 @@ dbus_server_unref (DBusServer *server)
}
}
void
_dbus_server_disconnect_unlocked (DBusServer *server)
{
_dbus_assert (server->vtable->disconnect != NULL);
if (!server->disconnected)
{
/* this has to be first so recursive calls to disconnect don't happen */
server->disconnected = TRUE;
(* server->vtable->disconnect) (server);
}
}
/**
* Releases the server's address and stops listening for
* new clients. If called more than once, only the first
......@@ -780,15 +794,7 @@ dbus_server_disconnect (DBusServer *server)
dbus_server_ref (server);
SERVER_LOCK (server);
_dbus_assert (server->vtable->disconnect != NULL);
if (!server->disconnected)
{
/* this has to be first so recursive calls to disconnect don't happen */
server->disconnected = TRUE;
(* server->vtable->disconnect) (server);
}
_dbus_server_disconnect_unlocked (server);
SERVER_UNLOCK (server);
dbus_server_unref (server);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment