static dbus_bool_t protected_change_watch (DBusServer *server, DBusWatch *watch, DBusWatchAddFunction add_function, DBusWatchRemoveFunction remove_function, DBusWatchToggleFunction toggle_function, dbus_bool_t enabled) { DBusWatchList *watches; dbus_bool_t retval; HAVE_LOCK_CHECK (server); /* This isn't really safe or reasonable; a better pattern is the "do * everything, then drop lock and call out" one; but it has to be * propagated up through all callers */ watches = server->watches; if (watches) { server->watches = NULL; _dbus_server_ref_unlocked (server); SERVER_UNLOCK (server); if (add_function) retval = (* add_function) (watches, watch); else if (remove_function) { retval = TRUE; (* remove_function) (watches, watch); } else { retval = TRUE; (* toggle_function) (watches, watch, enabled); } SERVER_LOCK (server); server->watches = watches; _dbus_server_unref_unlocked (server); return retval; } else return FALSE; }
static dbus_bool_t protected_change_timeout (DBusServer *server, DBusTimeout *timeout, DBusTimeoutAddFunction add_function, DBusTimeoutRemoveFunction remove_function, DBusTimeoutToggleFunction toggle_function, dbus_bool_t enabled) { DBusTimeoutList *timeouts; dbus_bool_t retval; HAVE_LOCK_CHECK (server); /* This isn't really safe or reasonable; a better pattern is the "do everything, then * drop lock and call out" one; but it has to be propagated up through all callers */ timeouts = server->timeouts; if (timeouts) { server->timeouts = NULL; _dbus_server_ref_unlocked (server); SERVER_UNLOCK (server); if (add_function) retval = (* add_function) (timeouts, timeout); else if (remove_function) { retval = TRUE; (* remove_function) (timeouts, timeout); } else { retval = TRUE; (* toggle_function) (timeouts, timeout, enabled); } SERVER_LOCK (server); server->timeouts = timeouts; _dbus_server_unref_unlocked (server); return retval; } else return FALSE; }
/** * Releases the server's address and stops listening for * new clients. If called more than once, only the first * call has an effect. Does not modify the server's * reference count. * * @param server the server. */ void dbus_server_disconnect (DBusServer *server) { _dbus_return_if_fail (server != NULL); _dbus_return_if_fail (server->refcount.value > 0); SERVER_LOCK (server); _dbus_server_ref_unlocked (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); } SERVER_UNLOCK (server); dbus_server_unref (server); }
/* Return value is just for memory, not other failures. */ static dbus_bool_t handle_new_client_fd_and_unlock (DBusServer *server, int client_fd) { DBusConnection *connection; DBusTransport *transport; DBusNewConnectionFunction new_connection_function; DBusServerSocket* socket_server; void *new_connection_data; socket_server = (DBusServerSocket*)server; _dbus_verbose ("Creating new client connection with fd %d\n", client_fd); HAVE_LOCK_CHECK (server); if (!_dbus_set_fd_nonblocking (client_fd, NULL)) { SERVER_UNLOCK (server); return TRUE; } transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, FALSE); if (transport == NULL) { _dbus_close_socket (client_fd, NULL); SERVER_UNLOCK (server); return FALSE; } if (!_dbus_transport_set_auth_mechanisms (transport, (const char **) server->auth_mechanisms)) { _dbus_transport_unref (transport); SERVER_UNLOCK (server); return FALSE; } /* note that client_fd is now owned by the transport, and will be * closed on transport disconnection/finalization */ connection = _dbus_connection_new_for_transport (transport); _dbus_transport_unref (transport); transport = NULL; /* now under the connection lock */ if (connection == NULL) { SERVER_UNLOCK (server); return FALSE; } /* See if someone wants to handle this new connection, self-referencing * for paranoia. */ new_connection_function = server->new_connection_function; new_connection_data = server->new_connection_data; _dbus_server_ref_unlocked (server); SERVER_UNLOCK (server); if (new_connection_function) { (* new_connection_function) (server, connection, new_connection_data); } dbus_server_unref (server); /* If no one grabbed a reference, the connection will die. */ _dbus_connection_close_if_only_one_ref (connection); dbus_connection_unref (connection); return TRUE; }