diff options
| author | Havoc Pennington <hp@redhat.com> | 2003-04-04 00:39:22 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2003-04-04 00:39:22 +0000 | 
| commit | 1b08036103a70159e7a67b2349306710edcd6654 (patch) | |
| tree | 6c6469bc51f9abcd2cf69036aabc71dea75c03b2 | |
| parent | f216e81432ddf04889202c33a6e68113f94d7611 (diff) | |
2003-04-03  Havoc Pennington  <hp@redhat.com>
	* bus/loop.h, bus/loop.c: make the mainloop an object so we can
	have multiple ones
	* bus/*.[hc]: adapt to mainloop change
| -rw-r--r-- | ChangeLog | 7 | ||||
| -rw-r--r-- | bus/bus.c | 154 | ||||
| -rw-r--r-- | bus/bus.h | 3 | ||||
| -rw-r--r-- | bus/connection.c | 58 | ||||
| -rw-r--r-- | bus/dispatch.c | 127 | ||||
| -rw-r--r-- | bus/loop.c | 166 | ||||
| -rw-r--r-- | bus/loop.h | 26 | ||||
| -rw-r--r-- | bus/main.c | 2 | ||||
| -rw-r--r-- | bus/test.c | 110 | ||||
| -rw-r--r-- | bus/test.h | 24 | ||||
| -rw-r--r-- | doc/TODO | 6 | 
11 files changed, 551 insertions, 132 deletions
| @@ -1,5 +1,12 @@  2003-04-03  Havoc Pennington  <hp@redhat.com> +	* bus/loop.h, bus/loop.c: make the mainloop an object so we can +	have multiple ones + +	* bus/*.[hc]: adapt to mainloop change + +2003-04-03  Havoc Pennington  <hp@redhat.com> +  	* bus/activation.c (load_directory): fix up memleaks  	(bus_activation_entry_free): free the entry @@ -38,6 +38,7 @@ struct BusContext    int refcount;    char *type;    char *address; +  BusLoop *loop;    DBusList *servers;    BusConnections *connections;    BusActivation *activation; @@ -48,6 +49,68 @@ struct BusContext    DBusHashTable *rules_by_gid;  /**< per-GID policy rules */  }; +static int server_data_slot = -1; +static int server_data_slot_refcount = 0; + +typedef struct +{ +  BusContext *context; +} BusServerData; + +#define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot)) + +static dbus_bool_t +server_data_slot_ref (void) +{ +  if (server_data_slot < 0) +    { +      server_data_slot = dbus_server_allocate_data_slot (); +       +      if (server_data_slot < 0) +        return FALSE; + +      _dbus_assert (server_data_slot_refcount == 0); +    }   + +  server_data_slot_refcount += 1; + +  return TRUE; +} + +static void +server_data_slot_unref (void) +{ +  _dbus_assert (server_data_slot_refcount > 0); + +  server_data_slot_refcount -= 1; +   +  if (server_data_slot_refcount == 0) +    { +      dbus_server_free_data_slot (server_data_slot); +      server_data_slot = -1; +    } +} + +static BusContext* +server_get_context (DBusServer *server) +{ +  BusContext *context; +  BusServerData *bd; +   +  if (!server_data_slot_ref ()) +    return NULL; + +  bd = BUS_SERVER_DATA (server); +  if (bd == NULL) +    return NULL; + +  context = bd->context; + +  server_data_slot_unref (); + +  return context; +} +  static dbus_bool_t  server_watch_callback (DBusWatch     *watch,                         unsigned int   condition, @@ -62,7 +125,13 @@ static dbus_bool_t  add_server_watch (DBusWatch  *watch,                    void       *data)  { -  return bus_loop_add_watch (watch, server_watch_callback, data, +  DBusServer *server = data; +  BusContext *context; +   +  context = server_get_context (server); +   +  return bus_loop_add_watch (context->loop, +                             watch, server_watch_callback, server,                               NULL);  } @@ -70,7 +139,13 @@ static void  remove_server_watch (DBusWatch  *watch,                       void       *data)  { -  bus_loop_remove_watch (watch, server_watch_callback, data); +  DBusServer *server = data; +  BusContext *context; +   +  context = server_get_context (server); +   +  bus_loop_remove_watch (context->loop, +                         watch, server_watch_callback, server);  } @@ -86,14 +161,26 @@ static dbus_bool_t  add_server_timeout (DBusTimeout *timeout,                      void        *data)  { -  return bus_loop_add_timeout (timeout, server_timeout_callback, data, NULL); +  DBusServer *server = data; +  BusContext *context; +   +  context = server_get_context (server); + +  return bus_loop_add_timeout (context->loop, +                               timeout, server_timeout_callback, server, NULL);  }  static void  remove_server_timeout (DBusTimeout *timeout,                         void        *data)  { -  bus_loop_remove_timeout (timeout, server_timeout_callback, data); +  DBusServer *server = data; +  BusContext *context; +   +  context = server_get_context (server); +   +  bus_loop_remove_timeout (context->loop, +                           timeout, server_timeout_callback, server);  }  static void @@ -139,12 +226,22 @@ free_rule_list_func (void *data)    dbus_free (list);  } +static void +free_server_data (void *data) +{ +  BusServerData *bd = data;   +   +  dbus_free (bd); +} +  static dbus_bool_t  setup_server (BusContext *context,                DBusServer *server,                char      **auth_mechanisms,                DBusError  *error)  { +  BusServerData *bd; +      if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))      {        BUS_SET_OOM (error); @@ -175,7 +272,18 @@ setup_server (BusContext *context,        BUS_SET_OOM (error);        return FALSE;      } +   +  bd = dbus_new0 (BusServerData, 1); +  if (!dbus_server_set_data (server, +                             server_data_slot, +                             bd, free_server_data)) +    { +      dbus_free (bd); +      return FALSE; +    } +  bd->context = context; +      return TRUE;  } @@ -196,8 +304,18 @@ bus_context_new (const DBusString *config_file,    _DBUS_ASSERT_ERROR_IS_CLEAR (error);    if (!_dbus_string_init (&full_address)) -    return NULL; - +    { +      BUS_SET_OOM (error); +      return NULL; +    } +   +  if (!server_data_slot_ref ()) +    { +      BUS_SET_OOM (error); +      _dbus_string_free (&full_address); +      return NULL; +    } +      parser = NULL;    context = NULL;    auth_mechanisms = NULL; @@ -215,6 +333,13 @@ bus_context_new (const DBusString *config_file,    context->refcount = 1; +  context->loop = bus_loop_new (); +  if (context->loop == NULL) +    { +      BUS_SET_OOM (error); +      goto failed; +    } +      /* Build an array of auth mechanisms */    auth_mechanisms_list = bus_config_parser_get_mechanisms (parser); @@ -401,6 +526,9 @@ bus_context_new (const DBusString *config_file,    _dbus_string_free (&full_address);    dbus_free_string_array (auth_mechanisms); + +  server_data_slot_unref (); +      return NULL;  } @@ -501,9 +629,17 @@ bus_context_unref (BusContext *context)            context->rules_by_gid = NULL;          } +      if (context->loop) +        { +          bus_loop_unref (context->loop); +          context->loop = NULL; +        } +              dbus_free (context->type);        dbus_free (context->address);        dbus_free (context); + +      server_data_slot_unref ();      }  } @@ -532,6 +668,12 @@ bus_context_get_activation (BusContext  *context)    return context->activation;  } +BusLoop* +bus_context_get_loop (BusContext *context) +{ +  return context->loop; +} +  static dbus_bool_t  list_allows_user (dbus_bool_t           def,                    DBusList            **list, @@ -29,6 +29,8 @@  #include <dbus/dbus.h>  #include <dbus/dbus-string.h> +#include "loop.h" +  typedef struct BusActivation  BusActivation;  typedef struct BusConnections BusConnections;  typedef struct BusContext     BusContext; @@ -47,6 +49,7 @@ const char*     bus_context_get_type                 (BusContext       *context)  BusRegistry*    bus_context_get_registry             (BusContext       *context);  BusConnections* bus_context_get_connections          (BusContext       *context);  BusActivation*  bus_context_get_activation           (BusContext       *context); +BusLoop*        bus_context_get_loop                 (BusContext       *context);  dbus_bool_t     bus_context_allow_user               (BusContext       *context,                                                        unsigned long     uid);  BusPolicy*      bus_context_create_connection_policy (BusContext       *context, diff --git a/bus/connection.c b/bus/connection.c index 3c43200f..aa8d65ca 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -89,6 +89,16 @@ connection_data_slot_unref (void)      }  } +static BusLoop* +connection_get_loop (DBusConnection *connection) +{ +  BusConnectionData *d; + +  d = BUS_CONNECTION_DATA (connection); + +  return bus_context_get_loop (d->connections->context); +} +  void  bus_connection_disconnected (DBusConnection *connection)  { @@ -195,17 +205,23 @@ connection_watch_callback (DBusWatch     *watch,  static dbus_bool_t  add_connection_watch (DBusWatch      *watch, -                      DBusConnection *connection) +                      void           *data)  { -  return bus_loop_add_watch (watch, connection_watch_callback, connection, +  DBusConnection *connection = data; + +  return bus_loop_add_watch (connection_get_loop (connection), +                             watch, connection_watch_callback, connection,                               NULL);  }  static void  remove_connection_watch (DBusWatch      *watch, -                         DBusConnection *connection) +                         void           *data)  { -  bus_loop_remove_watch (watch, connection_watch_callback, connection); +  DBusConnection *connection = data; +   +  bus_loop_remove_watch (connection_get_loop (connection), +                         watch, connection_watch_callback, connection);  }  static void @@ -226,16 +242,22 @@ connection_timeout_callback (DBusTimeout   *timeout,  static dbus_bool_t  add_connection_timeout (DBusTimeout    *timeout, -                        DBusConnection *connection) +                        void           *data)  { -  return bus_loop_add_timeout (timeout, connection_timeout_callback, connection, NULL); +  DBusConnection *connection = data; +   +  return bus_loop_add_timeout (connection_get_loop (connection), +                               timeout, connection_timeout_callback, connection, NULL);  }  static void  remove_connection_timeout (DBusTimeout    *timeout, -                           DBusConnection *connection) +                           void           *data)  { -  bus_loop_remove_timeout (timeout, connection_timeout_callback, connection); +  DBusConnection *connection = data; +   +  bus_loop_remove_timeout (connection_get_loop (connection), +                           timeout, connection_timeout_callback, connection);  }  static dbus_bool_t @@ -366,16 +388,16 @@ bus_connections_setup_connection (BusConnections *connections,    d->group_ids = NULL;    if (!dbus_connection_set_watch_functions (connection, -                                            (DBusAddWatchFunction) add_connection_watch, -                                            (DBusRemoveWatchFunction) remove_connection_watch, +                                            add_connection_watch, +                                            remove_connection_watch,                                              NULL,                                              connection,                                              NULL))      goto out;    if (!dbus_connection_set_timeout_functions (connection, -                                              (DBusAddTimeoutFunction) add_connection_timeout, -                                              (DBusRemoveTimeoutFunction) remove_connection_timeout, +                                              add_connection_timeout, +                                              remove_connection_timeout,                                                NULL,                                                connection, NULL))      goto out; @@ -400,12 +422,7 @@ bus_connections_setup_connection (BusConnections *connections,   out:    if (!retval) -    { -      if (!dbus_connection_set_data (connection, -                                     connection_data_slot, -                                     NULL, NULL)) -        _dbus_assert_not_reached ("failed to set connection data to null"); -         +    {                if (!dbus_connection_set_watch_functions (connection,                                                  NULL, NULL, NULL,                                                  connection, @@ -420,6 +437,11 @@ bus_connections_setup_connection (BusConnections *connections,        dbus_connection_set_unix_user_function (connection,                                                NULL, NULL, NULL); + +      if (!dbus_connection_set_data (connection, +                                     connection_data_slot, +                                     NULL, NULL)) +        _dbus_assert_not_reached ("failed to set connection data to null");      }    return retval; diff --git a/bus/dispatch.c b/bus/dispatch.c index 7c65ac42..21d57ae1 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -537,8 +537,8 @@ kill_client_connection (BusContext     *context,    /* kick in the disconnect handler that unrefs the connection */    dbus_connection_disconnect (connection); -  bus_test_flush_bus (context); - +  bus_test_run_everything (context); +      _dbus_assert (bus_test_client_listed (connection));    /* Run disconnect handler in test.c */ @@ -729,8 +729,8 @@ check_hello_message (BusContext     *context,    dbus_message_unref (message);    message = NULL; -   -  bus_test_flush_bus (context); + +  bus_test_run_everything (context);    if (!dbus_connection_get_is_connected (connection))      { @@ -963,8 +963,8 @@ check_nonexistent_service_activation (BusContext     *context,    dbus_message_unref (message);    message = NULL; -   -  bus_test_flush_bus (context); + +  bus_test_run_everything (context);    if (!dbus_connection_get_is_connected (connection))      { @@ -1028,6 +1028,116 @@ check_nonexistent_service_activation (BusContext     *context,    return retval;  } +#define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService" + +/* returns TRUE if the correct thing happens, + * but the correct thing may include OOM errors. + */ +static dbus_bool_t +check_existent_service_activation (BusContext     *context, +                                   DBusConnection *connection) +{ +  DBusMessage *message; +  dbus_int32_t serial; +  dbus_bool_t retval; +  DBusError error; +   +  dbus_error_init (&error); +   +  message = dbus_message_new (DBUS_SERVICE_DBUS, +			      DBUS_MESSAGE_ACTIVATE_SERVICE); + +  if (message == NULL) +    return TRUE; + +  if (!dbus_message_append_args (message, +                                 DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME, +                                 DBUS_TYPE_UINT32, 0, +                                 DBUS_TYPE_INVALID)) +    { +      dbus_message_unref (message); +      return TRUE; +    } +   +  if (!dbus_connection_send (connection, message, &serial)) +    { +      dbus_message_unref (message); +      return TRUE; +    } + +  dbus_message_unref (message); +  message = NULL; + +  bus_test_run_everything (context); + +  /* now wait for the message bus to hear back from the activated service */ +  bus_test_run_bus_loop (context); + +  /* and process everything again */ +  bus_test_run_everything (context); + +  if (!dbus_connection_get_is_connected (connection)) +    { +      _dbus_verbose ("connection was disconnected\n"); +      return TRUE; +    } +   +  retval = FALSE; +   +  message = dbus_connection_pop_message (connection); +  if (message == NULL) +    { +      _dbus_warn ("Did not receive a reply to %s %d on %p\n", +                  DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection); +      goto out; +    } + +  _dbus_verbose ("Received %s on %p\n", +                 dbus_message_get_name (message), connection); + +  if (dbus_message_get_is_error (message)) +    { +      if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS)) +        { +          _dbus_warn ("Message has wrong sender %s\n", +                      dbus_message_get_sender (message) ? +                      dbus_message_get_sender (message) : "(none)"); +          goto out; +        } +       +      if (dbus_message_name_is (message, +                                DBUS_ERROR_NO_MEMORY)) +        { +          ; /* good, this is a valid response */ +        } +      else if (dbus_message_name_is (message, +                                     DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND)) +        { +          ; /* good, this is expected also */ +        } +      else +        { +          _dbus_warn ("Did not expect error %s\n", +                      dbus_message_get_name (message)); +          goto out; +        } +    } +  else +    { +      _dbus_warn ("Did not expect to successfully activate %s\n", +                  EXISTENT_SERVICE_NAME); +      goto out; +    } + +  retval = TRUE; +   + out: +  if (message) +    dbus_message_unref (message); +   +  return retval; +} +  typedef struct  {    Check1Func func; @@ -1153,6 +1263,11 @@ bus_dispatch_test (const DBusString *test_data_dir)    if (!check_hello_message (context, baz))      _dbus_assert_not_reached ("hello message failed"); +#if 0 +  check2_try_iterations (context, foo, "existent_service_activation", +                         check_existent_service_activation); +#endif +      check2_try_iterations (context, foo, "nonexistent_service_activation",                           check_nonexistent_service_activation); @@ -26,11 +26,15 @@  #include <dbus/dbus-list.h>  #include <dbus/dbus-sysdeps.h> -static DBusList *callbacks = NULL; -static int callback_list_serial = 0; -static int watch_count = 0; -static int timeout_count = 0; -static dbus_bool_t exited = FALSE; +struct BusLoop +{ +  int refcount; +  DBusList *callbacks; +  int callback_list_serial; +  int watch_count; +  int timeout_count; +  int depth; /**< number of recursive runs */ +};  typedef enum  { @@ -121,20 +125,21 @@ callback_free (Callback *cb)  }  static dbus_bool_t -add_callback (Callback *cb) +add_callback (BusLoop  *loop, +              Callback *cb)  { -  if (!_dbus_list_append (&callbacks, cb)) +  if (!_dbus_list_append (&loop->callbacks, cb))      return FALSE; -  callback_list_serial += 1; +  loop->callback_list_serial += 1;    switch (cb->type)      {      case CALLBACK_WATCH: -      watch_count += 1; +      loop->watch_count += 1;        break;      case CALLBACK_TIMEOUT: -      timeout_count += 1; +      loop->timeout_count += 1;        break;      } @@ -142,27 +147,66 @@ add_callback (Callback *cb)  }  static void -remove_callback (DBusList *link) +remove_callback (BusLoop  *loop, +                 DBusList *link)  {    Callback *cb = link->data;    switch (cb->type)      {      case CALLBACK_WATCH: -      watch_count -= 1; +      loop->watch_count -= 1;        break;      case CALLBACK_TIMEOUT: -      timeout_count -= 1; +      loop->timeout_count -= 1;        break;      }    callback_free (cb); -  _dbus_list_remove_link (&callbacks, link); -  callback_list_serial += 1; +  _dbus_list_remove_link (&loop->callbacks, link); +  loop->callback_list_serial += 1; +} + +BusLoop* +bus_loop_new (void) +{ +  BusLoop *loop; + +  loop = dbus_new0 (BusLoop, 1); +  if (loop == NULL) +    return NULL; + +  loop->refcount = 1; +   +  return loop; +} + +void +bus_loop_ref (BusLoop *loop) +{ +  _dbus_assert (loop != NULL); +  _dbus_assert (loop->refcount > 0); + +  loop->refcount += 1; +} + +void +bus_loop_unref (BusLoop *loop) +{ +  _dbus_assert (loop != NULL); +  _dbus_assert (loop->refcount > 0); + +  loop->refcount -= 1; +  if (loop->refcount == 0) +    { +       +      dbus_free (loop); +    }  }  dbus_bool_t -bus_loop_add_watch (DBusWatch        *watch, +bus_loop_add_watch (BusLoop          *loop, +                    DBusWatch        *watch,                      BusWatchFunction  function,                      void             *data,                      DBusFreeFunction  free_data_func) @@ -173,7 +217,7 @@ bus_loop_add_watch (DBusWatch        *watch,    if (wcb == NULL)      return FALSE; -  if (!add_callback ((Callback*) wcb)) +  if (!add_callback (loop, (Callback*) wcb))      {        wcb->callback.free_data_func = NULL; /* don't want to have this side effect */        callback_free ((Callback*) wcb); @@ -184,16 +228,17 @@ bus_loop_add_watch (DBusWatch        *watch,  }  void -bus_loop_remove_watch (DBusWatch        *watch, +bus_loop_remove_watch (BusLoop          *loop, +                       DBusWatch        *watch,                         BusWatchFunction  function,                         void             *data)  {    DBusList *link; -  link = _dbus_list_get_first_link (&callbacks); +  link = _dbus_list_get_first_link (&loop->callbacks);    while (link != NULL)      { -      DBusList *next = _dbus_list_get_next_link (&callbacks, link); +      DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);        Callback *this = link->data;        if (this->type == CALLBACK_WATCH && @@ -201,7 +246,7 @@ bus_loop_remove_watch (DBusWatch        *watch,            this->data == data &&            WATCH_CALLBACK (this)->function == function)          { -          remove_callback (link); +          remove_callback (loop, link);            return;          } @@ -214,7 +259,8 @@ bus_loop_remove_watch (DBusWatch        *watch,  }  dbus_bool_t -bus_loop_add_timeout (DBusTimeout        *timeout, +bus_loop_add_timeout (BusLoop            *loop, +                      DBusTimeout        *timeout,                        BusTimeoutFunction  function,                        void               *data,                        DBusFreeFunction    free_data_func) @@ -225,7 +271,7 @@ bus_loop_add_timeout (DBusTimeout        *timeout,    if (tcb == NULL)      return FALSE; -  if (!add_callback ((Callback*) tcb)) +  if (!add_callback (loop, (Callback*) tcb))      {        tcb->callback.free_data_func = NULL; /* don't want to have this side effect */        callback_free ((Callback*) tcb); @@ -236,16 +282,17 @@ bus_loop_add_timeout (DBusTimeout        *timeout,  }  void -bus_loop_remove_timeout (DBusTimeout        *timeout, +bus_loop_remove_timeout (BusLoop            *loop, +                         DBusTimeout        *timeout,                           BusTimeoutFunction  function,                           void               *data)  {    DBusList *link; -  link = _dbus_list_get_first_link (&callbacks); +  link = _dbus_list_get_first_link (&loop->callbacks);    while (link != NULL)      { -      DBusList *next = _dbus_list_get_next_link (&callbacks, link); +      DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);        Callback *this = link->data;        if (this->type == CALLBACK_TIMEOUT && @@ -253,7 +300,7 @@ bus_loop_remove_timeout (DBusTimeout        *timeout,            this->data == data &&            TIMEOUT_CALLBACK (this)->function == function)          { -          remove_callback (link); +          remove_callback (loop, link);            return;          } @@ -270,7 +317,8 @@ bus_loop_remove_timeout (DBusTimeout        *timeout,   */  dbus_bool_t -bus_loop_iterate (dbus_bool_t block) +bus_loop_iterate (BusLoop     *loop, +                  dbus_bool_t  block)  {    dbus_bool_t retval;    DBusPollFD *fds; @@ -282,30 +330,32 @@ bus_loop_iterate (dbus_bool_t block)    int initial_serial;    long timeout;    dbus_bool_t oom_watch_pending; +  int orig_depth;    retval = FALSE;    fds = NULL;    watches_for_fds = NULL;    oom_watch_pending = FALSE; - +  orig_depth = loop->depth; +    #if 0    _dbus_verbose (" iterate %d timeouts %d watches\n", -                 timeout_count, watch_count); +                 loop->timeout_count, loop->watch_count);  #endif -  if (callbacks == NULL) +  if (loop->callbacks == NULL)      { -      bus_loop_quit (); +      bus_loop_quit (loop);        goto next_iteration;      }    /* count enabled watches */    n_fds = 0; -  link = _dbus_list_get_first_link (&callbacks); +  link = _dbus_list_get_first_link (&loop->callbacks);    while (link != NULL)      { -      DBusList *next = _dbus_list_get_next_link (&callbacks, link); +      DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);        Callback *cb = link->data;        if (cb->type == CALLBACK_WATCH)          { @@ -337,10 +387,10 @@ bus_loop_iterate (dbus_bool_t block)          }        i = 0; -      link = _dbus_list_get_first_link (&callbacks); +      link = _dbus_list_get_first_link (&loop->callbacks);        while (link != NULL)          { -          DBusList *next = _dbus_list_get_next_link (&callbacks, link); +          DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);            Callback *cb = link->data;            if (cb->type == CALLBACK_WATCH)              { @@ -378,7 +428,7 @@ bus_loop_iterate (dbus_bool_t block)      }    timeout = -1; -  if (timeout_count > 0) +  if (loop->timeout_count > 0)      {        unsigned long tv_sec;        unsigned long tv_usec; @@ -387,10 +437,10 @@ bus_loop_iterate (dbus_bool_t block)        _dbus_get_current_time (&tv_sec, &tv_usec); -      link = _dbus_list_get_first_link (&callbacks); +      link = _dbus_list_get_first_link (&loop->callbacks);        while (link != NULL)          { -          DBusList *next = _dbus_list_get_next_link (&callbacks, link); +          DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);            Callback *cb = link->data;            if (cb->type == CALLBACK_TIMEOUT && @@ -446,9 +496,9 @@ bus_loop_iterate (dbus_bool_t block)    n_ready = _dbus_poll (fds, n_fds, timeout); -  initial_serial = callback_list_serial; +  initial_serial = loop->callback_list_serial; -  if (timeout_count > 0) +  if (loop->timeout_count > 0)      {        unsigned long tv_sec;        unsigned long tv_usec; @@ -456,16 +506,16 @@ bus_loop_iterate (dbus_bool_t block)        _dbus_get_current_time (&tv_sec, &tv_usec);        /* It'd be nice to avoid this O(n) thingy here */ -      link = _dbus_list_get_first_link (&callbacks); +      link = _dbus_list_get_first_link (&loop->callbacks);        while (link != NULL)          { -          DBusList *next = _dbus_list_get_next_link (&callbacks, link); +          DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);            Callback *cb = link->data; -          if (initial_serial != callback_list_serial) +          if (initial_serial != loop->callback_list_serial)              goto next_iteration; -          if (exited) +          if (loop->depth != orig_depth)              goto next_iteration;            if (cb->type == CALLBACK_TIMEOUT && @@ -528,10 +578,10 @@ bus_loop_iterate (dbus_bool_t block)             * approach could result in starving watches             * toward the end of the list.             */ -          if (initial_serial != callback_list_serial) +          if (initial_serial != loop->callback_list_serial)              goto next_iteration; -          if (exited) +          if (loop->depth != orig_depth)              goto next_iteration;            if (fds[i].revents != 0) @@ -578,16 +628,26 @@ bus_loop_iterate (dbus_bool_t block)    return retval;  } -  void -bus_loop_run (void) +bus_loop_run (BusLoop *loop)  { -  while (!exited) -    bus_loop_iterate (TRUE); +  int our_exit_depth; + +  bus_loop_ref (loop); +   +  our_exit_depth = loop->depth; +  loop->depth += 1; +   +  while (loop->depth != our_exit_depth) +    bus_loop_iterate (loop, TRUE); + +  bus_loop_unref (loop);  }  void -bus_loop_quit (void) +bus_loop_quit (BusLoop *loop)  { -  exited = TRUE; +  _dbus_assert (loop->depth > 0); +   +  loop->depth -= 1;  } @@ -26,28 +26,40 @@  #include <dbus/dbus.h> +typedef struct BusLoop BusLoop; +  typedef dbus_bool_t (* BusWatchFunction)   (DBusWatch     *watch,                                              unsigned int   condition,                                              void          *data);  typedef void        (* BusTimeoutFunction) (DBusTimeout   *timeout,                                              void          *data); -dbus_bool_t bus_loop_add_watch      (DBusWatch          *watch, + +BusLoop*    bus_loop_new            (void); +void        bus_loop_ref            (BusLoop            *loop); +void        bus_loop_unref          (BusLoop            *loop); +dbus_bool_t bus_loop_add_watch      (BusLoop            *loop, +                                     DBusWatch          *watch,                                       BusWatchFunction    function,                                       void               *data,                                       DBusFreeFunction    free_data_func); -void        bus_loop_remove_watch   (DBusWatch          *watch, +void        bus_loop_remove_watch   (BusLoop            *loop, +                                     DBusWatch          *watch,                                       BusWatchFunction    function,                                       void               *data); -dbus_bool_t bus_loop_add_timeout    (DBusTimeout        *timeout, +dbus_bool_t bus_loop_add_timeout    (BusLoop            *loop, +                                     DBusTimeout        *timeout,                                       BusTimeoutFunction  function,                                       void               *data,                                       DBusFreeFunction    free_data_func); -void        bus_loop_remove_timeout (DBusTimeout        *timeout, +void        bus_loop_remove_timeout (BusLoop            *loop, +                                     DBusTimeout        *timeout,                                       BusTimeoutFunction  function,                                       void               *data); -void        bus_loop_run            (void); -void        bus_loop_quit           (void); -dbus_bool_t bus_loop_iterate        (dbus_bool_t         block); +void        bus_loop_run            (BusLoop            *loop); +void        bus_loop_quit           (BusLoop            *loop); +dbus_bool_t bus_loop_iterate        (BusLoop            *loop, +                                     dbus_bool_t         block); +  #endif /* BUS_LOOP_H */ @@ -143,7 +143,7 @@ main (int argc, char **argv)      }    _dbus_verbose ("We are on D-Bus...\n"); -  bus_loop_run (); +  bus_loop_run (bus_context_get_loop (context));    bus_context_shutdown (context);    bus_context_unref (context); @@ -34,11 +34,12 @@   * are different from the real handlers in connection.c   */  static DBusList *clients = NULL; +static BusLoop *client_loop = NULL;  static dbus_bool_t  client_watch_callback (DBusWatch     *watch, -                           unsigned int   condition, -                           void          *data) +                       unsigned int   condition, +                       void          *data)  {    DBusConnection *connection = data;    dbus_bool_t retval; @@ -54,22 +55,28 @@ client_watch_callback (DBusWatch     *watch,  static dbus_bool_t  add_client_watch (DBusWatch      *watch, -                      DBusConnection *connection) +                  void           *data)  { -  return bus_loop_add_watch (watch, client_watch_callback, connection, +  DBusConnection *connection = data; +   +  return bus_loop_add_watch (client_loop, +                             watch, client_watch_callback, connection,                               NULL);  }  static void  remove_client_watch (DBusWatch      *watch, -                         DBusConnection *connection) +                     void           *data)  { -  bus_loop_remove_watch (watch, client_watch_callback, connection); +  DBusConnection *connection = data; +   +  bus_loop_remove_watch (client_loop, +                         watch, client_watch_callback, connection);  }  static void  client_timeout_callback (DBusTimeout   *timeout, -                             void          *data) +                         void          *data)  {    DBusConnection *connection = data; @@ -83,16 +90,20 @@ client_timeout_callback (DBusTimeout   *timeout,  static dbus_bool_t  add_client_timeout (DBusTimeout    *timeout, -                        DBusConnection *connection) +                    void           *data)  { -  return bus_loop_add_timeout (timeout, client_timeout_callback, connection, NULL); +  DBusConnection *connection = data; +   +  return bus_loop_add_timeout (client_loop, timeout, client_timeout_callback, connection, NULL);  }  static void  remove_client_timeout (DBusTimeout    *timeout, -                           DBusConnection *connection) +                       void           *data)  { -  bus_loop_remove_timeout (timeout, client_timeout_callback, connection); +  DBusConnection *connection = data; +   +  bus_loop_remove_timeout (client_loop, timeout, client_timeout_callback, connection);  }  static DBusHandlerResult @@ -105,9 +116,15 @@ client_disconnect_handler (DBusMessageHandler *handler,                   connection);    _dbus_list_remove (&clients, connection); -   +    dbus_connection_unref (connection); +  if (clients == NULL) +    { +      bus_loop_unref (client_loop); +      client_loop = NULL; +    } +      return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;  } @@ -179,18 +196,25 @@ bus_setup_debug_client (DBusConnection *connection)      }    retval = FALSE; + +  if (client_loop == NULL) +    { +      client_loop = bus_loop_new (); +      if (client_loop == NULL) +        goto out; +    }    if (!dbus_connection_set_watch_functions (connection, -                                            (DBusAddWatchFunction) add_client_watch, -                                            (DBusRemoveWatchFunction) remove_client_watch, +                                            add_client_watch, +                                            remove_client_watch,                                              NULL,                                              connection,                                              NULL))      goto out;    if (!dbus_connection_set_timeout_functions (connection, -                                              (DBusAddTimeoutFunction) add_client_timeout, -                                              (DBusRemoveTimeoutFunction) remove_client_timeout, +                                              add_client_timeout, +                                              remove_client_timeout,                                                NULL,                                                connection, NULL))      goto out; @@ -223,6 +247,12 @@ bus_setup_debug_client (DBusConnection *connection)                                               NULL, NULL, NULL, NULL, NULL);        _dbus_list_remove_last (&clients, connection); + +      if (clients == NULL) +        { +          bus_loop_unref (client_loop); +          client_loop = NULL; +        }      }    return retval; @@ -268,25 +298,45 @@ bus_test_client_listed (DBusConnection *connection)  }  void -bus_test_flush_bus (BusContext *context) +bus_test_run_clients_loop (void)  { -  /* This is race condition city, obviously. since we're all in one -   * process we can't block, we just have to wait for data we put in -   * one end of the debug pipe to come out the other end... -   * a more robust setup would be good. Blocking on the other -   * end of pipes we've pushed data into or something. -   * A simple hack might be to just make the debug server always -   * poll for read on the other end of the pipe after writing. -   */ -  while (bus_loop_iterate (FALSE)) +  if (client_loop == NULL) +    return; +   +  /* Do one blocking wait, since we're expecting data */ +  bus_loop_iterate (client_loop, TRUE); + +  /* Then mop everything up */ +  while (bus_loop_iterate (client_loop, FALSE))      ; -#if 0 -  _dbus_sleep_milliseconds (15); -#endif -  while (bus_loop_iterate (FALSE)) +} + +void +bus_test_run_bus_loop (BusContext *context) +{ +  /* Do one blocking wait, since we're expecting data */ +  bus_loop_iterate (bus_context_get_loop (context), TRUE); + +  /* Then mop everything up */ +  while (bus_loop_iterate (bus_context_get_loop (context), FALSE))      ;  } +void +bus_test_run_everything (BusContext *context) +{ +  int i; + +  i = 0; +  while (i < 2) +    { +      while (bus_loop_iterate (bus_context_get_loop (context), FALSE) || +             (client_loop == NULL || bus_loop_iterate (client_loop, FALSE))) +        ; +      ++i; +    } +} +  BusContext*  bus_context_new_test (const DBusString *test_data_dir,                        const char       *filename) @@ -32,17 +32,19 @@  #include <dbus/dbus-string.h>  #include "connection.h" -dbus_bool_t bus_dispatch_test        (const DBusString             *test_data_dir); -dbus_bool_t bus_policy_test          (const DBusString             *test_data_dir); -dbus_bool_t bus_config_parser_test   (const DBusString             *test_data_dir); -dbus_bool_t bus_setup_debug_client   (DBusConnection               *connection); -void        bus_test_clients_foreach (BusConnectionForeachFunction  function, -                                      void                         *data); -dbus_bool_t bus_test_client_listed   (DBusConnection               *connection); -void        bus_test_flush_bus       (BusContext                   *context); - -BusContext* bus_context_new_test     (const DBusString             *test_data_dir, -                                      const char                   *filename); +dbus_bool_t bus_dispatch_test         (const DBusString             *test_data_dir); +dbus_bool_t bus_policy_test           (const DBusString             *test_data_dir); +dbus_bool_t bus_config_parser_test    (const DBusString             *test_data_dir); +dbus_bool_t bus_setup_debug_client    (DBusConnection               *connection); +void        bus_test_clients_foreach  (BusConnectionForeachFunction  function, +                                       void                         *data); +dbus_bool_t bus_test_client_listed    (DBusConnection               *connection); +void        bus_test_run_bus_loop     (BusContext                   *context); +void        bus_test_run_clients_loop (void); +void        bus_test_run_everything   (BusContext                   *context); +BusContext* bus_context_new_test      (const DBusString             *test_data_dir, +                                       const char                   *filename); +  #endif @@ -59,3 +59,9 @@     to return an error that automatically gets turned into a message; most likely      some basic spec'ing out of the GLib/Qt level stubs/skels stuff will be      needed to understand the right approach. + + - sync up DBusWatch and DBusTimeout so that handle_watch() is a method on DBusWatch  +   similar to the way timeouts work + + - there are various bits of code to manage ref/unref of data slots, that should  +   be merged into a generic facility | 
