static void socket_disconnect (DBusServer *server) { DBusServerSocket *socket_server = (DBusServerSocket*) server; int i; HAVE_LOCK_CHECK (server); for (i = 0 ; i < socket_server->n_fds ; i++) { if (socket_server->watch[i]) { _dbus_server_remove_watch (server, socket_server->watch[i]); _dbus_watch_unref (socket_server->watch[i]); socket_server->watch[i] = NULL; } _dbus_close_socket (socket_server->fds[i], NULL); socket_server->fds[i] = -1; } if (socket_server->socket_name != NULL) { DBusString tmp; _dbus_string_init_const (&tmp, socket_server->socket_name); _dbus_delete_file (&tmp, NULL); } if (server->published_address) _dbus_daemon_unpublish_session_bus_address(); HAVE_LOCK_CHECK (server); }
/** * Like dbus_server_unref() but does not acquire the lock (must already be held) * * @param server the server. */ void _dbus_server_unref_unlocked (DBusServer *server) { dbus_int32_t old_refcount; /* Keep this in sync with dbus_server_unref */ _dbus_assert (server != NULL); HAVE_LOCK_CHECK (server); old_refcount = _dbus_atomic_dec (&server->refcount); _dbus_assert (old_refcount > 0); _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref_unlocked"); if (old_refcount == 1) { _dbus_assert (server->disconnected); SERVER_UNLOCK (server); _dbus_assert (server->vtable->finalize != NULL); (* server->vtable->finalize) (server); } }
/** * Like dbus_server_unref() but does not acquire the lock (must already be held) * * @param server the server. */ void _dbus_server_unref_unlocked (DBusServer *server) { dbus_bool_t last_unref; /* Keep this in sync with dbus_server_unref */ _dbus_assert (server != NULL); _dbus_assert (server->refcount.value > 0); HAVE_LOCK_CHECK (server); #ifdef DBUS_HAVE_ATOMIC_INT last_unref = (_dbus_atomic_dec (&server->refcount) == 1); #else _dbus_assert (server->refcount.value > 0); server->refcount.value -= 1; last_unref = (server->refcount.value == 0); #endif if (last_unref) { _dbus_assert (server->disconnected); SERVER_UNLOCK (server); _dbus_assert (server->vtable->finalize != NULL); (* server->vtable->finalize) (server); } }
/** * Adds a watch for this server, chaining out to application-provided * watch handlers. * * @param server the server. * @param watch the watch to add. */ dbus_bool_t _dbus_server_add_watch (DBusServer *server, DBusWatch *watch) { HAVE_LOCK_CHECK (server); return protected_change_watch (server, watch, _dbus_watch_list_add_watch, NULL, NULL, FALSE); }
/** * Removes a watch previously added with _dbus_server_remove_watch(). * * @param server the server. * @param watch the watch to remove. */ void _dbus_server_remove_watch (DBusServer *server, DBusWatch *watch) { HAVE_LOCK_CHECK (server); protected_change_watch (server, watch, NULL, _dbus_watch_list_remove_watch, NULL, FALSE); }
/** * Like dbus_server_ref() but does not acquire the lock (must already be held) * * @param server the server. */ void _dbus_server_ref_unlocked (DBusServer *server) { dbus_int32_t old_refcount; _dbus_assert (server != NULL); HAVE_LOCK_CHECK (server); old_refcount = _dbus_atomic_inc (&server->refcount); _dbus_assert (old_refcount > 0); _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref_unlocked"); }
/** * Toggles a watch and notifies app via server's * DBusWatchToggledFunction if available. It's an error to call this * function on a watch that was not previously added. * * @param server the server. * @param watch the watch to toggle. * @param enabled whether to enable or disable */ void _dbus_server_toggle_watch (DBusServer *server, DBusWatch *watch, dbus_bool_t enabled) { _dbus_assert (watch != NULL); HAVE_LOCK_CHECK (server); protected_change_watch (server, watch, NULL, NULL, _dbus_watch_list_toggle_watch, enabled); }
/** * Like dbus_server_ref() but does not acquire the lock (must already be held) * * @param server the server. */ void _dbus_server_ref_unlocked (DBusServer *server) { _dbus_assert (server != NULL); _dbus_assert (server->refcount.value > 0); HAVE_LOCK_CHECK (server); #ifdef DBUS_HAVE_ATOMIC_INT _dbus_atomic_inc (&server->refcount); #else _dbus_assert (server->refcount.value > 0); server->refcount.value += 1; #endif }
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; }
/* 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; }