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");  | 
