diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | bus/bus.c | 6 | ||||
-rw-r--r-- | bus/connection.c | 14 | ||||
-rw-r--r-- | bus/dispatch.c | 10 | ||||
-rw-r--r-- | bus/loop.c | 49 | ||||
-rw-r--r-- | bus/services.c | 12 | ||||
-rw-r--r-- | bus/test.c | 6 | ||||
-rw-r--r-- | dbus/dbus-connection-internal.h | 6 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 73 | ||||
-rw-r--r-- | dbus/dbus-connection.h | 51 | ||||
-rw-r--r-- | dbus/dbus-server-protected.h | 16 | ||||
-rw-r--r-- | dbus/dbus-server-unix.c | 3 | ||||
-rw-r--r-- | dbus/dbus-server.c | 45 | ||||
-rw-r--r-- | dbus/dbus-server.h | 2 | ||||
-rw-r--r-- | dbus/dbus-timeout.c | 50 | ||||
-rw-r--r-- | dbus/dbus-timeout.h | 4 | ||||
-rw-r--r-- | dbus/dbus-transport-debug.c | 9 | ||||
-rw-r--r-- | dbus/dbus-transport-protected.h | 2 | ||||
-rw-r--r-- | dbus/dbus-transport-unix.c | 166 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 8 | ||||
-rw-r--r-- | dbus/dbus-transport.h | 2 | ||||
-rw-r--r-- | dbus/dbus-watch.c | 52 | ||||
-rw-r--r-- | dbus/dbus-watch.h | 8 | ||||
-rw-r--r-- | glib/dbus-gmain.c | 44 | ||||
-rw-r--r-- | test/watch.c | 99 |
25 files changed, 543 insertions, 224 deletions
@@ -1,5 +1,35 @@ 2003-03-15 Havoc Pennington <hp@pobox.com> + Make it pass the Hello handling test including all OOM codepaths. + Now to do other messages... + + * bus/services.c (bus_service_remove_owner): fix crash when + removing owner from an empty list of owners + (bus_registry_ensure): don't leave service in the list of + a connection's owned services if we fail to put the service + in the hash table. + + * bus/connection.c (bus_connection_preallocate_oom_error): set + error flag on the OOM error. + + * dbus/dbus-connection.c (_dbus_connection_new_for_transport): + handle _dbus_transport_set_connection failure + + * dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd): modify + to create watches up front and simply enable/disable them as + needed. + (unix_connection_set): this can now fail on OOM + + * dbus/dbus-timeout.c, dbus/dbus-watch.c: add concept + of enabling/disabling a watch or timeout. + + * bus/loop.c (bus_loop_iterate): don't touch disabled + watches/timeouts + + * glib/dbus-gmain.c: adapt to enable/disable watches and timeouts + +2003-03-15 Havoc Pennington <hp@pobox.com> + * bus/dispatch.c (bus_dispatch_test): OK, now finally actually write useful test code, after all that futzing around ;-) @@ -161,6 +161,7 @@ bus_context_new (const char *address, if (!dbus_server_set_watch_functions (context->server, (DBusAddWatchFunction) add_server_watch, (DBusRemoveWatchFunction) remove_server_watch, + NULL, context, NULL)) { @@ -171,6 +172,7 @@ bus_context_new (const char *address, if (!dbus_server_set_timeout_functions (context->server, (DBusAddTimeoutFunction) add_server_timeout, (DBusRemoveTimeoutFunction) remove_server_timeout, + NULL, context, NULL)) { BUS_SET_OOM (error); @@ -192,13 +194,13 @@ bus_context_shutdown (BusContext *context) return; if (!dbus_server_set_watch_functions (context->server, - NULL, NULL, + NULL, NULL, NULL, context, NULL)) _dbus_assert_not_reached ("setting watch functions to NULL failed"); if (!dbus_server_set_timeout_functions (context->server, - NULL, NULL, + NULL, NULL, NULL, context, NULL)) _dbus_assert_not_reached ("setting timeout functions to NULL failed"); diff --git a/bus/connection.c b/bus/connection.c index 1c699c6f..ee3612ae 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -107,13 +107,13 @@ bus_connection_disconnected (DBusConnection *connection) /* no more watching */ if (!dbus_connection_set_watch_functions (connection, - NULL, NULL, + NULL, NULL, NULL, connection, NULL)) _dbus_assert_not_reached ("setting watch functions to NULL failed"); if (!dbus_connection_set_timeout_functions (connection, - NULL, NULL, + NULL, NULL, NULL, connection, NULL)) _dbus_assert_not_reached ("setting timeout functions to NULL failed"); @@ -288,6 +288,7 @@ bus_connections_setup_connection (BusConnections *connections, if (!dbus_connection_set_watch_functions (connection, (DBusAddWatchFunction) add_connection_watch, (DBusRemoveWatchFunction) remove_connection_watch, + NULL, connection, NULL)) { @@ -298,6 +299,7 @@ bus_connections_setup_connection (BusConnections *connections, if (!dbus_connection_set_timeout_functions (connection, (DBusAddTimeoutFunction) add_connection_timeout, (DBusRemoveTimeoutFunction) remove_connection_timeout, + NULL, connection, NULL)) { dbus_connection_disconnect (connection); @@ -442,6 +444,8 @@ bus_connection_preallocate_oom_error (DBusConnection *connection) return FALSE; } + dbus_message_set_is_error (message, TRUE); + /* set reply serial to placeholder value just so space is already allocated * for it. */ @@ -603,6 +607,9 @@ bus_transaction_send_message (BusTransaction *transaction, BusConnectionData *d; DBusList *link; + _dbus_verbose (" trying to add message %s to transaction\n", + dbus_message_get_name (message)); + if (!dbus_connection_get_is_connected (connection)) return TRUE; /* silently ignore disconnected connections */ @@ -789,6 +796,9 @@ bus_transaction_send_error_reply (BusTransaction *transaction, _dbus_assert (error != NULL); _DBUS_ASSERT_ERROR_IS_SET (error); + + _dbus_verbose (" trying to add error %s to transaction\n", + error->name); reply = dbus_message_new_error_reply (in_reply_to, error->name, diff --git a/bus/dispatch.c b/bus/dispatch.c index ac2fb15b..d0def78f 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -514,6 +514,7 @@ check_hello_connection (BusContext *context) if (!bus_setup_debug_client (connection)) { + dbus_connection_disconnect (connection); dbus_connection_unref (connection); return TRUE; } @@ -582,9 +583,6 @@ bus_dispatch_test (const DBusString *test_data_dir) &error); if (context == NULL) _dbus_assert_not_reached ("could not alloc context"); - - check1_try_iterations (context, "create_and_hello", - check_hello_connection); foo = dbus_connection_open ("debug-pipe:name=test-server", &result); if (foo == NULL) @@ -610,8 +608,14 @@ bus_dispatch_test (const DBusString *test_data_dir) if (!check_hello_message (context, baz)) _dbus_assert_not_reached ("hello message failed"); + check1_try_iterations (context, "create_and_hello", + check_hello_connection); + + dbus_connection_disconnect (foo); dbus_connection_unref (foo); + dbus_connection_disconnect (bar); dbus_connection_unref (bar); + dbus_connection_disconnect (baz); dbus_connection_unref (baz); return TRUE; @@ -294,9 +294,26 @@ bus_loop_iterate (dbus_bool_t block) bus_loop_quit (); goto next_iteration; } + + /* count enabled watches */ + n_fds = 0; + link = _dbus_list_get_first_link (&callbacks); + while (link != NULL) + { + DBusList *next = _dbus_list_get_next_link (&callbacks, link); + Callback *cb = link->data; + if (cb->type == CALLBACK_WATCH) + { + WatchCallback *wcb = WATCH_CALLBACK (cb); + + if (dbus_watch_get_enabled (wcb->watch)) + ++n_fds; + } - n_fds = watch_count; + link = next; + } + /* fill our array of fds and watches */ if (n_fds > 0) { fds = dbus_new0 (DBusPollFD, n_fds); @@ -323,18 +340,21 @@ bus_loop_iterate (dbus_bool_t block) { unsigned int flags; WatchCallback *wcb = WATCH_CALLBACK (cb); + + if (dbus_watch_get_enabled (wcb->watch)) + { + watches_for_fds[i] = wcb; - watches_for_fds[i] = wcb; - - flags = dbus_watch_get_flags (wcb->watch); + flags = dbus_watch_get_flags (wcb->watch); - fds[i].fd = dbus_watch_get_fd (wcb->watch); - if (flags & DBUS_WATCH_READABLE) - fds[i].events |= _DBUS_POLLIN; - if (flags & DBUS_WATCH_WRITABLE) - fds[i].events |= _DBUS_POLLOUT; + fds[i].fd = dbus_watch_get_fd (wcb->watch); + if (flags & DBUS_WATCH_READABLE) + fds[i].events |= _DBUS_POLLIN; + if (flags & DBUS_WATCH_WRITABLE) + fds[i].events |= _DBUS_POLLOUT; - ++i; + ++i; + } } link = next; @@ -359,7 +379,8 @@ bus_loop_iterate (dbus_bool_t block) DBusList *next = _dbus_list_get_next_link (&callbacks, link); Callback *cb = link->data; - if (cb->type == CALLBACK_TIMEOUT) + if (cb->type == CALLBACK_TIMEOUT && + dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) { TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); unsigned long interval; @@ -427,7 +448,8 @@ bus_loop_iterate (dbus_bool_t block) if (exited) goto next_iteration; - if (cb->type == CALLBACK_TIMEOUT) + if (cb->type == CALLBACK_TIMEOUT && + dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) { TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); unsigned long interval; @@ -513,7 +535,8 @@ bus_loop_iterate (dbus_bool_t block) * weird POLLFOO thing like POLLWRBAND */ - if (condition != 0) + if (condition != 0 && + dbus_watch_get_enabled (wcb->watch)) { (* wcb->function) (wcb->watch, condition, diff --git a/bus/services.c b/bus/services.c index 9508b2f7..92f6cdf4 100644 --- a/bus/services.c +++ b/bus/services.c @@ -170,6 +170,8 @@ bus_registry_ensure (BusRegistry *registry, service->name, service)) { + bus_connection_remove_owned_service (owner_if_created, + service); _dbus_list_clear (&service->owners); dbus_free (service->name); _dbus_mem_pool_dealloc (registry->service_pool, service); @@ -290,7 +292,11 @@ bus_service_remove_owner (BusService *service, return FALSE; } - if (_dbus_list_length_is_one (&service->owners)) + if (service->owners == NULL) + { + _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners"); + } + else if (_dbus_list_length_is_one (&service->owners)) { /* We are the only owner - send service deleted */ if (!bus_driver_send_service_deleted (service->name, @@ -301,6 +307,7 @@ bus_service_remove_owner (BusService *service, { DBusList *link; link = _dbus_list_get_first (&service->owners); + _dbus_assert (link != NULL); link = _dbus_list_get_next_link (&service->owners, link); if (link != NULL) @@ -320,7 +327,8 @@ bus_service_remove_owner (BusService *service, if (service->owners == NULL) { /* Delete service (already sent message that it was deleted above) */ - _dbus_hash_table_remove_string (service->registry->service_hash, service->name); + _dbus_hash_table_remove_string (service->registry->service_hash, + service->name); dbus_free (service->name); _dbus_mem_pool_dealloc (service->registry->service_pool, service); @@ -127,6 +127,7 @@ bus_setup_debug_client (DBusConnection *connection) if (!dbus_connection_set_watch_functions (connection, (DBusAddWatchFunction) add_client_watch, (DBusRemoveWatchFunction) remove_client_watch, + NULL, connection, NULL)) goto out; @@ -134,6 +135,7 @@ bus_setup_debug_client (DBusConnection *connection) if (!dbus_connection_set_timeout_functions (connection, (DBusAddTimeoutFunction) add_client_timeout, (DBusRemoveTimeoutFunction) remove_client_timeout, + NULL, connection, NULL)) goto out; @@ -148,9 +150,9 @@ bus_setup_debug_client (DBusConnection *connection) _DBUS_N_ELEMENTS (to_handle)); dbus_connection_set_watch_functions (connection, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); dbus_connection_set_timeout_functions (connection, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); } dbus_message_handler_unref (disconnect_handler); diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index 64c4cf39..4d3ed130 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -55,10 +55,16 @@ dbus_bool_t _dbus_connection_add_watch (DBusConnection *connect DBusWatch *watch); void _dbus_connection_remove_watch (DBusConnection *connection, DBusWatch *watch); +void _dbus_connection_toggle_watch (DBusConnection *connection, + DBusWatch *watch, + dbus_bool_t enabled); dbus_bool_t _dbus_connection_add_timeout (DBusConnection *connection, DBusTimeout *timeout); void _dbus_connection_remove_timeout (DBusConnection *connection, DBusTimeout *timeout); +void _dbus_connection_toggle_timeout (DBusConnection *connection, + DBusTimeout *timeout, + dbus_bool_t enabled); DBusConnection* _dbus_connection_new_for_transport (DBusTransport *transport); void _dbus_connection_do_iteration (DBusConnection *connection, diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index c5df5611..780c410f 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -331,6 +331,25 @@ _dbus_connection_remove_watch (DBusConnection *connection, } /** + * Toggles a watch and notifies app via connection's + * DBusWatchToggledFunction if available. It's an error to call this + * function on a watch that was not previously added. + * + * @param connection the connection. + * @param timeout the timeout to toggle. + * @param enabled whether to enable or disable + */ +void +_dbus_connection_toggle_watch (DBusConnection *connection, + DBusWatch *watch, + dbus_bool_t enabled) +{ + if (connection->watches) /* null during finalize */ + _dbus_watch_list_toggle_watch (connection->watches, + watch, enabled); +} + +/** * Adds a timeout using the connection's DBusAddTimeoutFunction if * available. Otherwise records the timeout to be added when said * function is available. Also re-adds the timeout if the @@ -378,6 +397,24 @@ _dbus_connection_remove_timeout_locked (DBusConnection *connection, dbus_mutex_unlock (connection->mutex); } +/** + * Toggles a timeout and notifies app via connection's + * DBusTimeoutToggledFunction if available. It's an error to call this + * function on a timeout that was not previously added. + * + * @param connection the connection. + * @param timeout the timeout to toggle. + * @param enabled whether to enable or disable + */ +void +_dbus_connection_toggle_timeout (DBusConnection *connection, + DBusTimeout *timeout, + dbus_bool_t enabled) +{ + if (connection->timeouts) /* null during finalize */ + _dbus_timeout_list_toggle_timeout (connection->timeouts, + timeout, enabled); +} /** * Tells the connection that the transport has been disconnected. @@ -598,8 +635,10 @@ _dbus_connection_new_for_transport (DBusTransport *transport) connection->disconnect_message_link = disconnect_link; - _dbus_transport_ref (transport); - _dbus_transport_set_connection (transport, connection); + if (!_dbus_transport_set_connection (transport, connection)) + goto error; + + _dbus_transport_ref (transport); return connection; @@ -1793,8 +1832,18 @@ dbus_connection_dispatch_message (DBusConnection *connection) * poll(). When using Qt, typically the DBusAddWatchFunction would * create a QSocketNotifier. When using GLib, the DBusAddWatchFunction * could call g_io_add_watch(), or could be used as part of a more - * elaborate GSource. - * + * elaborate GSource. Note that when a watch is added, it may + * not be enabled. + * + * The DBusWatchToggledFunction notifies the application that the + * watch has been enabled or disabled. Call dbus_watch_get_enabled() + * to check this. A disabled watch should have no effect, and enabled + * watch should be added to the main loop. This feature is used + * instead of simply adding/removing the watch because + * enabling/disabling can be done without memory allocation. The + * toggled function may be NULL if a main loop re-queries + * dbus_watch_get_enabled() every time anyway. + * * The DBusWatch can be queried for the file descriptor to watch using * dbus_watch_get_fd(), and for the events to watch for using * dbus_watch_get_flags(). The flags returned by @@ -1825,6 +1874,7 @@ dbus_connection_dispatch_message (DBusConnection *connection) * @param connection the connection. * @param add_function function to begin monitoring a new descriptor. * @param remove_function function to stop monitoring a descriptor. + * @param toggled_function function to notify of enable/disable * @param data data to pass to add_function and remove_function. * @param free_data_function function to be called to free the data. * @returns #FALSE on failure (no memory) @@ -1833,6 +1883,7 @@ dbus_bool_t dbus_connection_set_watch_functions (DBusConnection *connection, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { @@ -1844,6 +1895,7 @@ dbus_connection_set_watch_functions (DBusConnection *connection, retval = _dbus_watch_list_set_functions (connection->watches, add_function, remove_function, + toggled_function, data, free_data_function); dbus_mutex_unlock (connection->mutex); @@ -1859,6 +1911,16 @@ dbus_connection_set_watch_functions (DBusConnection *connection, * When using Qt, typically the DBusAddTimeoutFunction would create a * QTimer. When using GLib, the DBusAddTimeoutFunction would call * g_timeout_add. + * + * The DBusTimeoutToggledFunction notifies the application that the + * timeout has been enabled or disabled. Call + * dbus_timeout_get_enabled() to check this. A disabled timeout should + * have no effect, and enabled timeout should be added to the main + * loop. This feature is used instead of simply adding/removing the + * timeout because enabling/disabling can be done without memory + * allocation. With Qt, QTimer::start() and QTimer::stop() can be used + * to enable and disable. The toggled function may be NULL if a main + * loop re-queries dbus_timeout_get_enabled() every time anyway. * * The DBusTimeout can be queried for the timer interval using * dbus_timeout_get_interval(). dbus_timeout_handle() should @@ -1869,6 +1931,7 @@ dbus_connection_set_watch_functions (DBusConnection *connection, * @param connection the connection. * @param add_function function to add a timeout. * @param remove_function function to remove a timeout. + * @param toggled_function function to notify of enable/disable * @param data data to pass to add_function and remove_function. * @param free_data_function function to be called to free the data. * @returns #FALSE on failure (no memory) @@ -1877,6 +1940,7 @@ dbus_bool_t dbus_connection_set_timeout_functions (DBusConnection *connection, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { @@ -1888,6 +1952,7 @@ dbus_connection_set_timeout_functions (DBusConnection *connection, retval = _dbus_timeout_list_set_functions (connection->timeouts, add_function, remove_function, + toggled_function, data, free_data_function); dbus_mutex_unlock (connection->mutex); diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index bf0983e6..78a8d58c 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -56,15 +56,19 @@ typedef enum * can be present in current state). */ } DBusWatchFlags; -typedef dbus_bool_t (* DBusAddWatchFunction) (DBusWatch *watch, - void *data); -typedef void (* DBusRemoveWatchFunction) (DBusWatch *watch, - void *data); -typedef void (* DBusWakeupMainFunction) (void *data); -typedef dbus_bool_t (* DBusAddTimeoutFunction) (DBusTimeout *timeout, - void *data); -typedef void (* DBusRemoveTimeoutFunction) (DBusTimeout *timeout, - void *data); +typedef dbus_bool_t (* DBusAddWatchFunction) (DBusWatch *watch, + void *data); +typedef void (* DBusWatchToggledFunction) (DBusWatch *watch, + void *data); +typedef void (* DBusRemoveWatchFunction) (DBusWatch *watch, + void *data); +typedef void (* DBusWakeupMainFunction) (void *data); +typedef dbus_bool_t (* DBusAddTimeoutFunction) (DBusTimeout *timeout, + void *data); +typedef void (* DBusTimeoutToggledFunction) (DBusTimeout *timeout, + void *data); +typedef void (* DBusRemoveTimeoutFunction) (DBusTimeout *timeout, + void *data); DBusConnection* dbus_connection_open (const char *address, DBusResultCode *result); @@ -100,11 +104,13 @@ DBusMessage *dbus_connection_send_with_reply_and_block (DBusConnection *conn dbus_bool_t dbus_connection_set_watch_functions (DBusConnection *connection, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); dbus_bool_t dbus_connection_set_timeout_functions (DBusConnection *connection, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); void dbus_connection_set_wakeup_main_function (DBusConnection *connection, @@ -118,20 +124,21 @@ void dbus_connection_handle_watch (DBusConnection -int dbus_watch_get_fd (DBusWatch *watch); -unsigned int dbus_watch_get_flags (DBusWatch *watch); -void* dbus_watch_get_data (DBusWatch *watch); -void dbus_watch_set_data (DBusWatch *watch, - void *data, - DBusFreeFunction free_data_function); - -int dbus_timeout_get_interval (DBusTimeout *timeout); -void* dbus_timeout_get_data (DBusTimeout *timeout); -void dbus_timeout_set_data (DBusTimeout *timeout, - void *data, - DBusFreeFunction free_data_function); -void dbus_timeout_handle (DBusTimeout *timeout); +int dbus_watch_get_fd (DBusWatch *watch); +unsigned int dbus_watch_get_flags (DBusWatch *watch); +void* dbus_watch_get_data (DBusWatch *watch); +void dbus_watch_set_data (DBusWatch *watch, + void *data, + DBusFreeFunction free_data_function); +dbus_bool_t dbus_watch_get_enabled (DBusWatch *watch); +int dbus_timeout_get_interval (DBusTimeout *timeout); +void* dbus_timeout_get_data (DBusTimeout *timeout); +void dbus_timeout_set_data (DBusTimeout *timeout, + void *data, + DBusFreeFunction free_data_function); +void dbus_timeout_handle (DBusTimeout *timeout); +dbus_bool_t dbus_timeout_get_enabled (DBusTimeout *timeout); /* Handlers */ dbus_bool_t dbus_connection_add_filter (DBusConnection *connection, diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h index 24b805c4..bbedeea3 100644 --- a/dbus/dbus-server-protected.h +++ b/dbus/dbus-server-protected.h @@ -78,16 +78,22 @@ struct DBusServer }; dbus_bool_t _dbus_server_init_base (DBusServer *server, - const DBusServerVTable *vtable); + const DBusServerVTable *vtable); void _dbus_server_finalize_base (DBusServer *server); dbus_bool_t _dbus_server_add_watch (DBusServer *server, - DBusWatch *watch); + DBusWatch *watch); void _dbus_server_remove_watch (DBusServer *server, - DBusWatch *watch); + DBusWatch *watch); +void _dbus_server_toggle_watch (DBusServer *server, + DBusWatch *watch, + dbus_bool_t enabled); dbus_bool_t _dbus_server_add_timeout (DBusServer *server, - DBusTimeout *timeout); + DBusTimeout *timeout); void _dbus_server_remove_timeout (DBusServer *server, - DBusTimeout *timeout); + DBusTimeout *timeout); +void _dbus_server_toggle_timeout (DBusServer *server, + DBusTimeout *timeout, + dbus_bool_t enabled); diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 0a98c53c..a181a925 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -204,7 +204,8 @@ _dbus_server_new_for_fd (int fd) DBusWatch *watch; watch = _dbus_watch_new (fd, - DBUS_WATCH_READABLE); + DBUS_WATCH_READABLE, + TRUE); if (watch == NULL) return NULL; diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 80ee6fc2..48703e17 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -146,6 +146,25 @@ _dbus_server_remove_watch (DBusServer *server, } /** + * 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 timeout the timeout to toggle. + * @param enabled whether to enable or disable + */ +void +_dbus_server_toggle_watch (DBusServer *server, + DBusWatch *watch, + dbus_bool_t enabled) +{ + if (server->watches) /* null during finalize */ + _dbus_watch_list_toggle_watch (server->watches, + watch, enabled); +} + +/** * Adds a timeout for this server, chaining out to * application-provided timeout handlers. The timeout should be * repeatedly handled with dbus_timeout_handle() at its given interval @@ -174,6 +193,26 @@ _dbus_server_remove_timeout (DBusServer *server, _dbus_timeout_list_remove_timeout (server->timeouts, timeout); } +/** + * Toggles a timeout and notifies app via server's + * DBusTimeoutToggledFunction if available. It's an error to call this + * function on a timeout that was not previously added. + * + * @param server the server. + * @param timeout the timeout to toggle. + * @param enabled whether to enable or disable + */ +void +_dbus_server_toggle_timeout (DBusServer *server, + DBusTimeout *timeout, + dbus_bool_t enabled) +{ + if (server->timeouts) /* null during finalize */ + _dbus_timeout_list_toggle_timeout (server->timeouts, + timeout, enabled); +} + + /** @} */ /** @@ -405,6 +444,7 @@ dbus_server_set_new_connection_function (DBusServer *server, * @param server the server. * @param add_function function to begin monitoring a new descriptor. * @param remove_function function to stop monitoring a descriptor. + * @param toggled_function function to notify when the watch is enabled/disabled * @param data data to pass to add_function and remove_function. * @param free_data_function function to be called to free the data. * @returns #FALSE on failure (no memory) @@ -413,12 +453,14 @@ dbus_bool_t dbus_server_set_watch_functions (DBusServer *server, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { return _dbus_watch_list_set_functions (server->watches, add_function, remove_function, + toggled_function, data, free_data_function); } @@ -433,6 +475,7 @@ dbus_server_set_watch_functions (DBusServer *server, * @param server the server. * @param add_function function to add a timeout. * @param remove_function function to remove a timeout. + * @param toggled_function function to notify when the timeout is enabled/disabled * @param data data to pass to add_function and remove_function. * @param free_data_function function to be called to free the data. * @returns #FALSE on failure (no memory) @@ -441,11 +484,13 @@ dbus_bool_t dbus_server_set_timeout_functions (DBusServer *server, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { return _dbus_timeout_list_set_functions (server->timeouts, add_function, remove_function, + toggled_function, data, free_data_function); } diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index 6665335b..589237f1 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -52,11 +52,13 @@ void dbus_server_set_new_connection_function (DBusServer * dbus_bool_t dbus_server_set_watch_functions (DBusServer *server, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); dbus_bool_t dbus_server_set_timeout_functions (DBusServer *server, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); void dbus_server_handle_watch (DBusServer *server, diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c index 09e54b31..9825872e 100644 --- a/dbus/dbus-timeout.c +++ b/dbus/dbus-timeout.c @@ -44,6 +44,7 @@ struct DBusTimeout void *data; /**< Application data. */ DBusFreeFunction free_data_function; /**< Free the application data. */ + unsigned int enabled : 1; /**< True if timeout is active. */ }; /** @@ -69,6 +70,8 @@ _dbus_timeout_new (int interval, timeout->handler = handler; timeout->handler_data = data; timeout->free_handler_data_function = free_data_function; + + timeout->enabled = TRUE; return timeout; } @@ -130,6 +133,7 @@ struct DBusTimeoutList DBusAddTimeoutFunction add_timeout_function; /**< Callback for adding a timeout. */ DBusRemoveTimeoutFunction remove_timeout_function; /**< Callback for removing a timeout. */ + DBusTimeoutToggledFunction timeout_toggled_function; /**< Callback when timeout is enabled/disabled */ void *timeout_data; /**< Data for timeout callbacks */ DBusFreeFunction timeout_free_data_function; /**< Free function for timeout callback data */ }; @@ -162,7 +166,7 @@ _dbus_timeout_list_free (DBusTimeoutList *timeout_list) { /* free timeout_data and remove timeouts as a side effect */ _dbus_timeout_list_set_functions (timeout_list, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); _dbus_list_foreach (&timeout_list->timeouts, (DBusForeachFunction) _dbus_timeout_unref, @@ -179,6 +183,7 @@ _dbus_timeout_list_free (DBusTimeoutList *timeout_list) * @param timeout_list the timeout list * @param add_function the add timeout function. * @param remove_function the remove timeout function. + * @param toggled_function toggle notify function, or #NULL * @param data the data for those functions. * @param free_data_function the function to free the data. * @returns #FALSE if no memory @@ -188,6 +193,7 @@ dbus_bool_t _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { @@ -239,6 +245,7 @@ _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list, timeout_list->add_timeout_function = add_function; timeout_list->remove_timeout_function = remove_function; + timeout_list->timeout_toggled_function = toggled_function; timeout_list->timeout_data = data; timeout_list->timeout_free_data_function = free_data_function; @@ -297,6 +304,31 @@ _dbus_timeout_list_remove_timeout (DBusTimeoutList *timeout_list, _dbus_timeout_unref (timeout); } +/** + * Sets a timeout to the given enabled state, invoking the + * application's DBusTimeoutToggledFunction if appropriate. + * + * @param timeout_list the timeout list. + * @param timeout the timeout to toggle. + * @param enabled #TRUE to enable + */ +void +_dbus_timeout_list_toggle_timeout (DBusTimeoutList *timeout_list, + DBusTimeout *timeout, + dbus_bool_t enabled) +{ + enabled = !!enabled; + + if (enabled == timeout->enabled) + return; + + timeout->enabled = enabled; + + if (timeout_list->timeout_toggled_function != NULL) + (* timeout_list->timeout_toggled_function) (timeout, + timeout_list->timeout_data); +} + /** @} */ /** @@ -380,3 +412,19 @@ dbus_timeout_handle (DBusTimeout *timeout) { (* timeout->handler) (timeout->handler_data); } + + +/** + * Returns whether a timeout is enabled or not. If not + * enabled, it should not be polled by the main loop. + * + * @param timeout the DBusTimeout object + * @returns #TRUE if the timeout is enabled + */ +dbus_bool_t +dbus_timeout_get_enabled (DBusTimeout *timeout) +{ + return timeout->enabled; +} + +/** @} end public API docs */ diff --git a/dbus/dbus-timeout.h b/dbus/dbus-timeout.h index 2d7112a7..0ff5dc56 100644 --- a/dbus/dbus-timeout.h +++ b/dbus/dbus-timeout.h @@ -46,12 +46,16 @@ void _dbus_timeout_list_free (DBusTimeoutList *t dbus_bool_t _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); dbus_bool_t _dbus_timeout_list_add_timeout (DBusTimeoutList *timeout_list, DBusTimeout *timeout); void _dbus_timeout_list_remove_timeout (DBusTimeoutList *timeout_list, DBusTimeout *timeout); +void _dbus_timeout_list_toggle_timeout (DBusTimeoutList *timeout_list, + DBusTimeout *timeout, + dbus_bool_t enabled); DBUS_END_DECLS; diff --git a/dbus/dbus-transport-debug.c b/dbus/dbus-transport-debug.c index 42d1efdc..a7db3a6e 100644 --- a/dbus/dbus-transport-debug.c +++ b/dbus/dbus-transport-debug.c @@ -147,10 +147,8 @@ check_timeout (DBusTransport *transport) { if (!debug_transport->timeout_added) { - /* FIXME; messages_pending is going to have to - * handle OOM somehow (probably being part of - * PreallocatedSend). See also dbus-transport-unix.c - * check_write_watch() + /* FIXME this can be fixed now, by enabling/disabling + * the timeout instead of adding it here */ while (!_dbus_connection_add_timeout (transport->connection, debug_transport->timeout)) @@ -203,10 +201,11 @@ debug_disconnect (DBusTransport *transport) { } -static void +static dbus_bool_t debug_connection_set (DBusTransport *transport) { check_timeout (transport); + return TRUE; } static void diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 46dfe141..0f6c45ed 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -49,7 +49,7 @@ struct DBusTransportVTable void (* disconnect) (DBusTransport *transport); /**< Disconnect this transport. */ - void (* connection_set) (DBusTransport *transport); + dbus_bool_t (* connection_set) (DBusTransport *transport); /**< Called when transport->connection has been filled in */ void (* messages_pending) (DBusTransport *transport, diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 3c5fe848..23ab7c54 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -117,6 +117,12 @@ check_write_watch (DBusTransport *transport) if (transport->connection == NULL) return; + + if (transport->disconnected) + { + _dbus_assert (unix_transport->write_watch == NULL); + return; + } _dbus_transport_ref (transport); @@ -126,51 +132,10 @@ check_write_watch (DBusTransport *transport) need_write_watch = transport->send_credentials_pending || _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND; - if (transport->disconnected) - need_write_watch = FALSE; - - if (need_write_watch && - unix_transport->write_watch == NULL) - { - unix_transport->write_watch = - _dbus_watch_new (unix_transport->fd, - DBUS_WATCH_WRITABLE); - - /* FIXME this is total crack. The proper fix is probably to - * allocate the write watch on transport creation, keep it - * allocated. But that doesn't solve needing memory to add the - * watch. messages_pending is going to have to handle OOM - * somehow (probably being part of PreallocatedSend) - */ - if (unix_transport->write_watch == NULL) - goto out; + _dbus_connection_toggle_watch (transport->connection, + unix_transport->write_watch, + need_write_watch); - if (!_dbus_connection_add_watch (transport->connection, - unix_transport->write_watch)) - { - _dbus_watch_invalidate (unix_transport->write_watch); - _dbus_watch_unref (unix_transport->write_watch); - unix_transport->write_watch = NULL; - } - } - else if (!need_write_watch && - unix_transport->write_watch != NULL) - { - _dbus_connection_remove_watch (transport->connection, - unix_transport->write_watch); - _dbus_watch_invalidate (unix_transport->write_watch); - _dbus_watch_unref (unix_transport->write_watch); - unix_transport->write_watch = NULL; - } - else - { -#if 0 - _dbus_verbose ("Write watch is unchanged from %p on fd %d\n", - unix_transport->write_watch, unix_transport->fd); -#endif - } - - out: _dbus_transport_unref (transport); } @@ -182,6 +147,12 @@ check_read_watch (DBusTransport *transport) if (transport->connection == NULL) return; + + if (transport->disconnected) + { + _dbus_assert (unix_transport->read_watch == NULL); + return; + } _dbus_transport_ref (transport); @@ -192,57 +163,10 @@ check_read_watch (DBusTransport *transport) need_read_watch = transport->receive_credentials_pending || _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT; -#if 0 - _dbus_verbose ("need_read_watch = %d authenticated = %d\n", - need_read_watch, _dbus_transport_get_is_authenticated (transport)); -#endif - - if (transport->disconnected) - need_read_watch = FALSE; - - if (need_read_watch && - unix_transport->read_watch == NULL) - { - _dbus_verbose ("Adding read watch to unix fd %d\n", - unix_transport->fd); - - unix_transport->read_watch = - _dbus_watch_new (unix_transport->fd, - DBUS_WATCH_READABLE); + _dbus_connection_toggle_watch (transport->connection, + unix_transport->read_watch, + need_read_watch); - /* we can maybe add it some other time, just silently bomb */ - if (unix_transport->read_watch == NULL) - goto out; - - if (!_dbus_connection_add_watch (transport->connection, - unix_transport->read_watch)) - { - _dbus_watch_invalidate (unix_transport->read_watch); - _dbus_watch_unref (unix_transport->read_watch); - unix_transport->read_watch = NULL; - } - } - else if (!need_read_watch && - unix_transport->read_watch != NULL) - { - _dbus_verbose ("Removing read watch from unix fd %d\n", - unix_transport->fd); - - _dbus_connection_remove_watch (transport->connection, - unix_transport->read_watch); - _dbus_watch_invalidate (unix_transport->read_watch); - _dbus_watch_unref (unix_transport->read_watch); - unix_transport->read_watch = NULL; - } - else - { -#if 0 - _dbus_verbose ("Read watch is unchanged from %p on fd %d\n", - unix_transport->read_watch, unix_transport->fd); -#endif - } - - out: _dbus_transport_unref (transport); } @@ -908,11 +832,27 @@ unix_disconnect (DBusTransport *transport) unix_transport->fd = -1; } -static void +static dbus_bool_t unix_connection_set (DBusTransport *transport) { + DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; + + if (!_dbus_connection_add_watch (transport->connection, + unix_transport->write_watch)) + return FALSE; + + if (!_dbus_connection_add_watch (transport->connection, + unix_transport->read_watch)) + { + _dbus_connection_remove_watch (transport->connection, + unix_transport->write_watch); + return FALSE; + } + check_read_watch (transport); check_write_watch (transport); + + return TRUE; } static void @@ -1120,19 +1060,24 @@ _dbus_transport_new_for_fd (int fd, if (!_dbus_string_init (&unix_transport->encoded_message, _DBUS_INT_MAX)) - { - dbus_free (unix_transport); - return NULL; - } + goto failed_0; + + unix_transport->write_watch = _dbus_watch_new (fd, + DBUS_WATCH_WRITABLE, + FALSE); + if (unix_transport->write_watch == NULL) + goto failed_1; + + unix_transport->read_watch = _dbus_watch_new (fd, + DBUS_WATCH_READABLE, + FALSE); + if (unix_transport->read_watch == NULL) + goto failed_2; if (!_dbus_transport_init_base (&unix_transport->base, &unix_vtable, server)) - { - _dbus_string_free (&unix_transport->encoded_message); - dbus_free (unix_transport); - return NULL; - } + goto failed_3; unix_transport->fd = fd; unix_transport->message_bytes_written = 0; @@ -1140,11 +1085,18 @@ _dbus_transport_new_for_fd (int fd, /* These values should probably be tunable or something. */ unix_transport->max_bytes_read_per_iteration = 2048; unix_transport->max_bytes_written_per_iteration = 2048; - - check_read_watch ((DBusTransport*) unix_transport); - check_write_watch ((DBusTransport*) unix_transport); return (DBusTransport*) unix_transport; + + failed_3: + _dbus_watch_unref (unix_transport->read_watch); + failed_2: + _dbus_watch_unref (unix_transport->write_watch); + failed_1: + _dbus_string_free (&unix_transport->encoded_message); + failed_0: + dbus_free (unix_transport); + return NULL; } /** diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 03fea75b..8c6c7f1c 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -427,8 +427,9 @@ _dbus_transport_handle_watch (DBusTransport *transport, * * @param transport the transport. * @param connection the connection. + * @returns #FALSE if not enough memory */ -void +dbus_bool_t _dbus_transport_set_connection (DBusTransport *transport, DBusConnection *connection) { @@ -438,8 +439,11 @@ _dbus_transport_set_connection (DBusTransport *transport, transport->connection = connection; _dbus_transport_ref (transport); - (* transport->vtable->connection_set) (transport); + if (!(* transport->vtable->connection_set) (transport)) + transport->connection = NULL; _dbus_transport_unref (transport); + + return transport->connection != NULL; } /** diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 5e7de3e5..1f01788f 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -40,7 +40,7 @@ dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *trans void _dbus_transport_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int condition); -void _dbus_transport_set_connection (DBusTransport *transport, +dbus_bool_t _dbus_transport_set_connection (DBusTransport *transport, DBusConnection *connection); void _dbus_transport_messages_pending (DBusTransport *transport, int queue_length); diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c index ef2a0ed9..1fdbc7ac 100644 --- a/dbus/dbus-watch.c +++ b/dbus/dbus-watch.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-watch.c DBusWatch implementation * - * Copyright (C) 2002 Red Hat Inc. + * Copyright (C) 2002, 2003 Red Hat Inc. * * Licensed under the Academic Free License version 1.2 * @@ -40,6 +40,7 @@ struct DBusWatch unsigned int flags; /**< Conditions to watch. */ void *data; /**< Application data. */ DBusFreeFunction free_data_function; /**< Free the application data. */ + unsigned int enabled : 1; /**< Whether it's enabled. */ }; /** @@ -47,11 +48,13 @@ struct DBusWatch * implementation. * @param fd the file descriptor to be watched. * @param flags the conditions to watch for on the descriptor. + * @param enabled the initial enabled state * @returns the new DBusWatch object. */ DBusWatch* _dbus_watch_new (int fd, - unsigned int flags) + unsigned int flags, + dbus_bool_t enabled) { DBusWatch *watch; @@ -63,6 +66,7 @@ _dbus_watch_new (int fd, watch->refcount = 1; watch->fd = fd; watch->flags = flags; + watch->enabled = enabled; return watch; } @@ -160,6 +164,7 @@ struct DBusWatchList DBusAddWatchFunction add_watch_function; /**< Callback for adding a watch. */ DBusRemoveWatchFunction remove_watch_function; /**< Callback for removing a watch. */ + DBusWatchToggledFunction watch_toggled_function; /**< Callback on toggling enablement */ void *watch_data; /**< Data for watch callbacks */ DBusFreeFunction watch_free_data_function; /**< Free function for watch callback data */ }; @@ -192,7 +197,7 @@ _dbus_watch_list_free (DBusWatchList *watch_list) { /* free watch_data and removes watches as a side effect */ _dbus_watch_list_set_functions (watch_list, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); _dbus_list_foreach (&watch_list->watches, (DBusForeachFunction) _dbus_watch_unref, @@ -210,6 +215,7 @@ _dbus_watch_list_free (DBusWatchList *watch_list) * @param watch_list the watch list. * @param add_function the add watch function. * @param remove_function the remove watch function. + * @param toggled_function function on toggling enabled flag, or #NULL * @param data the data for those functions. * @param free_data_function the function to free the data. * @returns #FALSE if not enough memory @@ -219,6 +225,7 @@ dbus_bool_t _dbus_watch_list_set_functions (DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function) { @@ -270,6 +277,7 @@ _dbus_watch_list_set_functions (DBusWatchList *watch_list, watch_list->add_watch_function = add_function; watch_list->remove_watch_function = remove_function; + watch_list->watch_toggled_function = toggled_function; watch_list->watch_data = data; watch_list->watch_free_data_function = free_data_function; @@ -328,6 +336,31 @@ _dbus_watch_list_remove_watch (DBusWatchList *watch_list, _dbus_watch_unref (watch); } +/** + * Sets a watch to the given enabled state, invoking the + * application's DBusWatchToggledFunction if appropriate. + * + * @param watch_list the watch list. + * @param watch the watch to toggle. + * @param enabled #TRUE to enable + */ +void +_dbus_watch_list_toggle_watch (DBusWatchList *watch_list, + DBusWatch *watch, + dbus_bool_t enabled) +{ + enabled = !!enabled; + + if (enabled == watch->enabled) + return; + + watch->enabled = enabled; + + if (watch_list->watch_toggled_function != NULL) + (* watch_list->watch_toggled_function) (watch, + watch_list->watch_data); +} + /** @} */ /** @@ -419,4 +452,17 @@ dbus_watch_set_data (DBusWatch *watch, watch->free_data_function = free_data_function; } +/** + * Returns whether a watch is enabled or not. If not + * enabled, it should not be polled by the main loop. + * + * @param watch the DBusWatch object + * @returns #TRUE if the watch is enabled + */ +dbus_bool_t +dbus_watch_get_enabled (DBusWatch *watch) +{ + return watch->enabled; +} + /** @} */ diff --git a/dbus/dbus-watch.h b/dbus/dbus-watch.h index 9d85737e..7a9ec57c 100644 --- a/dbus/dbus-watch.h +++ b/dbus/dbus-watch.h @@ -33,7 +33,8 @@ DBUS_BEGIN_DECLS; typedef struct DBusWatchList DBusWatchList; DBusWatch* _dbus_watch_new (int fd, - unsigned int flags); + unsigned int flags, + dbus_bool_t enabled); void _dbus_watch_ref (DBusWatch *watch); void _dbus_watch_unref (DBusWatch *watch); void _dbus_watch_invalidate (DBusWatch *watch); @@ -46,13 +47,16 @@ void _dbus_watch_list_free (DBusWatchList *watch_li dbus_bool_t _dbus_watch_list_set_functions (DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); dbus_bool_t _dbus_watch_list_add_watch (DBusWatchList *watch_list, DBusWatch *watch); void _dbus_watch_list_remove_watch (DBusWatchList *watch_list, DBusWatch *watch); - +void _dbus_watch_list_toggle_watch (DBusWatchList *watch_list, + DBusWatch *watch, + dbus_bool_t enabled); DBUS_END_DECLS; diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 6ce13888..5eb75d10 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -238,6 +238,9 @@ add_watch (DBusWatch *watch, GPollFD *poll_fd; DBusGSource *dbus_source; guint flags; + + if (!dbus_watch_get_enabled (watch)) + return TRUE; dbus_source = data; @@ -269,6 +272,8 @@ remove_watch (DBusWatch *watch, GPollFD *poll_fd; poll_fd = dbus_watch_get_data (watch); + if (poll_fd == NULL) + return; /* probably a not-enabled watch that was added */ dbus_source->poll_fds = g_list_remove (dbus_source->poll_fds, poll_fd); g_hash_table_remove (dbus_source->watches, poll_fd); @@ -277,6 +282,19 @@ remove_watch (DBusWatch *watch, g_free (poll_fd); } +static void +watch_toggled (DBusWatch *watch, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_watch_get_enabled (watch)) + add_watch (watch, data); + else + remove_watch (watch, data); +} + static gboolean timeout_handler (gpointer data) { @@ -293,6 +311,9 @@ add_timeout (DBusTimeout *timeout, { guint timeout_tag; + if (!dbus_timeout_get_enabled (timeout)) + return TRUE; + timeout_tag = g_timeout_add (dbus_timeout_get_interval (timeout), timeout_handler, timeout); @@ -308,10 +329,25 @@ remove_timeout (DBusTimeout *timeout, guint timeout_tag; timeout_tag = GPOINTER_TO_UINT (dbus_timeout_get_data (timeout)); - - g_source_remove (timeout_tag); + + if (timeout_tag != 0) /* if 0, probably timeout was disabled */ + g_source_remove (timeout_tag); +} + +static void +timeout_toggled (DBusTimeout *timeout, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_timeout_get_enabled (timeout)) + add_timeout (timeout, data); + else + remove_timeout (timeout, data); } + static void free_source (GSource *source) { @@ -363,12 +399,14 @@ dbus_connection_setup_with_g_main (DBusConnection *connection) if (!dbus_connection_set_watch_functions (connection, add_watch, remove_watch, + watch_toggled, source, NULL)) goto nomem; if (!dbus_connection_set_timeout_functions (connection, add_timeout, remove_timeout, + timeout_toggled, NULL, NULL)) goto nomem; @@ -412,11 +450,13 @@ dbus_server_setup_with_g_main (DBusServer *server) dbus_server_set_watch_functions (server, add_watch, remove_watch, + watch_toggled, source, NULL); dbus_server_set_timeout_functions (server, add_timeout, remove_timeout, + timeout_toggled, NULL, NULL); g_source_attach (source, NULL); diff --git a/test/watch.c b/test/watch.c index 73f5e97d..bdb18306 100644 --- a/test/watch.c +++ b/test/watch.c @@ -237,24 +237,28 @@ do_mainloop (void) while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&watches, link); - int fd; DBusWatch *watch; - unsigned int flags; watch = link->data; - - fd = dbus_watch_get_fd (watch); - flags = dbus_watch_get_flags (watch); - - max_fd = MAX (max_fd, fd); - - if (flags & DBUS_WATCH_READABLE) - FD_SET (fd, &read_set); - - if (flags & DBUS_WATCH_WRITABLE) - FD_SET (fd, &write_set); - FD_SET (fd, &err_set); + if (dbus_watch_get_enabled (watch)) + { + int fd; + unsigned int flags; + + fd = dbus_watch_get_fd (watch); + flags = dbus_watch_get_flags (watch); + + max_fd = MAX (max_fd, fd); + + if (flags & DBUS_WATCH_READABLE) + FD_SET (fd, &read_set); + + if (flags & DBUS_WATCH_WRITABLE) + FD_SET (fd, &write_set); + + FD_SET (fd, &err_set); + } link = next; } @@ -266,10 +270,7 @@ do_mainloop (void) while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&watches, link); - int fd; DBusWatch *watch; - unsigned int flags; - unsigned int condition; if (initial_watch_serial != watch_list_serial) { @@ -286,44 +287,52 @@ do_mainloop (void) } watch = link->data; + + if (dbus_watch_get_enabled (watch)) + { + int fd; + unsigned int flags; + unsigned int condition; + - fd = dbus_watch_get_fd (watch); - flags = dbus_watch_get_flags (watch); + fd = dbus_watch_get_fd (watch); + flags = dbus_watch_get_flags (watch); - condition = 0; + condition = 0; - if ((flags & DBUS_WATCH_READABLE) && - FD_ISSET (fd, &read_set)) - condition |= DBUS_WATCH_READABLE; + if ((flags & DBUS_WATCH_READABLE) && + FD_ISSET (fd, &read_set)) + condition |= DBUS_WATCH_READABLE; - if ((flags & DBUS_WATCH_WRITABLE) && - FD_ISSET (fd, &write_set)) - condition |= DBUS_WATCH_WRITABLE; + if ((flags & DBUS_WATCH_WRITABLE) && + FD_ISSET (fd, &write_set)) + condition |= DBUS_WATCH_WRITABLE; - if (FD_ISSET (fd, &err_set)) - condition |= DBUS_WATCH_ERROR; + if (FD_ISSET (fd, &err_set)) + condition |= DBUS_WATCH_ERROR; - if (condition != 0) - { - WatchData *wd; + if (condition != 0) + { + WatchData *wd; - wd = dbus_watch_get_data (watch); + wd = dbus_watch_get_data (watch); - if (wd->type == WATCH_CONNECTION) - { - DBusConnection *connection = wd->data; + if (wd->type == WATCH_CONNECTION) + { + DBusConnection *connection = wd->data; - dbus_connection_handle_watch (connection, + dbus_connection_handle_watch (connection, + watch, + condition); + } + else if (wd->type == WATCH_SERVER) + { + DBusServer *server = wd->data; + + dbus_server_handle_watch (server, watch, condition); - } - else if (wd->type == WATCH_SERVER) - { - DBusServer *server = wd->data; - - dbus_server_handle_watch (server, - watch, - condition); + } } } @@ -345,6 +354,7 @@ setup_connection (DBusConnection *connection) if (!dbus_connection_set_watch_functions (connection, (DBusAddWatchFunction) add_connection_watch, (DBusRemoveWatchFunction) remove_connection_watch, + NULL, connection, NULL)) _dbus_assert_not_reached ("not enough memory"); @@ -359,6 +369,7 @@ setup_server (DBusServer *server) if (!dbus_server_set_watch_functions (server, (DBusAddWatchFunction) add_server_watch, (DBusRemoveWatchFunction) remove_server_watch, + NULL, server, NULL)) _dbus_assert_not_reached ("not enough memory"); |