[Patch] Auto-Close dbus-daemon when unused

Leon Winter <winter-dbus-E/QL+Cw/[email protected]>
Newsgroups gmane.comp.freedesktop.dbus
Message-ID <[email protected]>
Hi,

we are running a Debian-based thin client setup with a central big machine and
several lightweight clients. Since users run normal desktop applications like
evince or firefox, dbus-daemons for their sessions are started. When they log
out however, the dbus-daemons continue to linger around. Often only a single
application during the whole session requires dbus. Yet after the dbus-daemon is
initially launched, it sticks around. This all results in many dbus-daemon
processes running without any use. Thus for our setup we would like the
dbus-daemon to automatically terminate when it is not actually used any more.
To accomplish just that, we patched dbus to keep track of the connected clients
and auto-launched services. Additionally it sets up a timer. Once the timer
expires, dbus checks if anyone actually uses it and conditionally quits.

At this point, I would like to ask if upstream would be willing to adapt such a
(optional) behaviour. Unlike most users, we are not running dbus on a single
user machine but share it with many users. Additionally we are not rebooting the
system for each session. Also most our applications are not requiring dbus which
might be uncommon for Linux Desktop environments. Therefore I assume our setup
differs a lot from a the average desktop user and the mentioned feature might be
unfit for upstream inclusion.

We have already implemented said feature in our dbus. The code quality should be
considered "proof of concept". Albeit we are using it for many years now, it is
not of best quality. This mostly stems from the fact that certain data
structures need to be modified at locations where it is currently not desired to
do so. To modify such structures one does need to know their design which was
currently specified in the .c implementation and was ripped out into a header
file.

In the end it comes down to the questions:
- Would you consider such a (optional) feature (to included upstream)?
- Would you consider changing some internal APIs/structures to make it easier to
  add such a feature downstream?
- Do you know another way of running dbus achieving the same effect but without
  modifications?

To give you an idea of the PoC for the feature I included a patch which applies
to the Debian source package of dbus 1.10.

Thanks,
Leon Winter

_______________________________________________
dbus mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dbus
dbus-1.10.diff (text/x-diff, 25.9 KB)
diff --git a/Makefile.am b/Makefile.am
index 756ab8b..27ed715 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS=dbus bus tools test doc
+SUBDIRS=dbus bus tools doc
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = dbus-1.pc
diff --git a/bus/activation.c b/bus/activation.c
index 679a40e..b5a23c2 100644
--- a/bus/activation.c
+++ b/bus/activation.c
@@ -31,6 +31,8 @@
 #include "services.h"
 #include "test.h"
 #include "utils.h"
+#include <dbus/dbus-server.h>
+#include <dbus/dbus-server-protected.h>
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-list.h>
@@ -41,6 +43,10 @@
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
+#include <dbus/dbus-bus.h>
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-object-tree.h>
+#include <dbus/dbus-dataslot.h>
 
 struct BusActivation
 {
@@ -1085,11 +1091,19 @@ add_restore_pending_to_transaction (BusTransaction       *transaction,
   return TRUE;
 }
 
+#include <bus/buscontext.h>
+
+struct DBusConnection
+{
+  char autolaunched;
+};
+
 dbus_bool_t
 bus_activation_service_created (BusActivation  *activation,
                                 const char     *service_name,
                                 BusTransaction *transaction,
-                                DBusError      *error)
+                                DBusError      *error,
+                                DBusConnection *connection)
 {
   BusPendingActivation *pending_activation;
   DBusMessage *message;
@@ -1103,6 +1117,9 @@ bus_activation_service_created (BusActivation  *activation,
   if (!pending_activation)
     return TRUE;
 
+  ++((DBusServer*) activation->context->servers->data)->service_count;
+  connection->autolaunched = 1;
+
   bus_context_log (activation->context,
                    DBUS_SYSTEM_LOG_INFO, "Successfully activated service '%s'",
                    service_name);
diff --git a/bus/activation.h b/bus/activation.h
index fc5d426..54fcb11 100644
--- a/bus/activation.h
+++ b/bus/activation.h
@@ -53,7 +53,8 @@ dbus_bool_t    bus_activation_activate_service (BusActivation     *activation,
 dbus_bool_t    bus_activation_service_created  (BusActivation     *activation,
 						const char        *service_name,
 						BusTransaction    *transaction,
-						DBusError         *error);
+						DBusError         *error,
+						DBusConnection    *connection);
 dbus_bool_t    bus_activation_list_services    (BusActivation     *registry,
 						char            ***listp,
 						int               *array_len);
diff --git a/bus/bus.c b/bus/bus.c
index 128ae3c..d2d771c 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -42,38 +42,13 @@
 #include <dbus/dbus-credentials.h>
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-server-protected.h>
+#include <dbus/dbus-server.h>
 
 #ifdef DBUS_CYGWIN
 #include <signal.h>
 #endif
 
-struct BusContext
-{
-  int refcount;
-  DBusGUID uuid;
-  char *config_file;
-  char *type;
-  char *servicehelper;
-  char *address;
-  char *pidfile;
-  char *user;
-  char *log_prefix;
-  DBusLoop *loop;
-  DBusList *servers;
-  BusConnections *connections;
-  BusActivation *activation;
-  BusRegistry *registry;
-  BusPolicy *policy;
-  BusMatchmaker *matchmaker;
-  BusLimits limits;
-  DBusRLimit *initial_fd_limit;
-  unsigned int fork : 1;
-  unsigned int syslog : 1;
-  unsigned int keep_umask : 1;
-  unsigned int allow_anonymous : 1;
-  unsigned int systemd_activation : 1;
-  dbus_bool_t watches_enabled;
-};
+#include <bus/buscontext.h>
 
 static dbus_int32_t server_data_slot = -1;
 
@@ -727,8 +702,6 @@ process_config_postinit (BusContext      *context,
       return FALSE;
     }
 
-  bus_set_watched_dirs (context, &watched_dirs);
-
   _dbus_list_clear (&watched_dirs);
 
   return TRUE;
diff --git a/bus/bus.h b/bus/bus.h
index 3fab59f..48b7cc4 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -140,4 +140,5 @@ dbus_bool_t       bus_context_check_security_policy              (BusContext
                                                                   DBusError        *error);
 void              bus_context_check_all_watches                  (BusContext       *context);
 
+static const int idle_timeout = 15 * 1000; /* milliseconds */
 #endif /* BUS_BUS_H */
diff --git a/bus/buscontext.h b/bus/buscontext.h
new file mode 100644
index 0000000..9fc2a80
--- /dev/null
+++ b/bus/buscontext.h
@@ -0,0 +1,27 @@
+struct BusContext
+{
+  int refcount;
+  DBusGUID uuid;
+  char *config_file;
+  char *type;
+  char *servicehelper;
+  char *address;
+  char *pidfile;
+  char *user;
+  char *log_prefix;
+  DBusLoop *loop;
+  DBusList *servers;
+  BusConnections *connections;
+  BusActivation *activation;
+  BusRegistry *registry;
+  BusPolicy *policy;
+  BusMatchmaker *matchmaker;
+  BusLimits limits;
+  DBusRLimit *initial_fd_limit;
+  unsigned int fork : 1;
+  unsigned int syslog : 1;
+  unsigned int keep_umask : 1;
+  unsigned int allow_anonymous : 1;
+  unsigned int systemd_activation : 1;
+  dbus_bool_t watches_enabled;
+};
diff --git a/bus/main.c b/bus/main.c
index ee5e1eb..ae12f59 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -26,6 +26,11 @@
 #include "driver.h"
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-watch.h>
+#include <dbus/dbus-mainloop.h>
+#include <dbus/dbus-timeout.h>
+#include <dbus/dbus-server.h>
+#include <dbus/dbus-server-protected.h>
+#include <dbus/dbus-list.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -60,6 +65,10 @@ typedef enum
    ACTION_QUIT = 'q'
  } SignalAction;
 
+/* time to wait after the daemon was started to shut it down
+   this is only relevant when nobody talks to the daemon, otherwise it
+   would shutdown after the disconnect of the last client */
+
 static void
 signal_handler (int sig)
 {
@@ -363,6 +372,25 @@ close_reload_pipe (DBusWatch **watch)
 }
 #endif /* DBUS_UNIX */
 
+#include <dbus/dbusloop.h>
+
+#include <bus/buscontext.h>
+
+struct timerdataptr
+{
+  DBusLoop *loop;
+  BusContext *context;
+  DBusTimeout *timeout;
+};
+static dbus_bool_t
+delayhandler (void *data)
+{
+  ((DBusLoop*) ((struct timerdataptr*) data)->loop)->delaydone = 1;
+  ((DBusServer*) ((struct timerdataptr*) data)->context->servers->data)->delaydone = 1;
+  _dbus_loop_remove_timeout ((DBusLoop*) ((struct timerdataptr*) data)->loop, (DBusTimeout*) ((struct timerdataptr*) data)->timeout);
+  return TRUE;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -378,6 +406,8 @@ main (int argc, char **argv)
   dbus_bool_t print_address;
   dbus_bool_t print_pid;
   BusContextFlags flags;
+  DBusLoop *loop;
+  struct timerdataptr timer_data_ptr;
 
   if (!_dbus_string_init (&config_file))
     return 1;
@@ -645,7 +675,6 @@ main (int argc, char **argv)
    */
 
 #ifdef DBUS_UNIX
-  setup_reload_pipe (bus_context_get_loop (context));
 
   /* POSIX signals are Unix-specific, and _dbus_set_signal_handler is
    * unimplemented (and probably unimplementable) on Windows, so there's
@@ -656,7 +685,15 @@ main (int argc, char **argv)
 #endif /* DBUS_UNIX */
 
   _dbus_verbose ("We are on D-Bus...\n");
-  _dbus_loop_run (bus_context_get_loop (context));
+  loop = bus_context_get_loop (context);
+
+  loop->delaydone = 0;
+  ((DBusServer*) context->servers->data)->delaydone = 0;
+  timer_data_ptr.loop = loop;
+  timer_data_ptr.context = context;
+  timer_data_ptr.timeout = _dbus_timeout_new (idle_timeout, delayhandler, (void*) &timer_data_ptr, NULL);
+  _dbus_loop_add_timeout (loop, timer_data_ptr.timeout);
+  _dbus_loop_run (loop, context);
 
   bus_context_shutdown (context);
   bus_context_unref (context);
diff --git a/bus/services.c b/bus/services.c
index 6a4c884..787b88b 100644
--- a/bus/services.c
+++ b/bus/services.c
@@ -291,7 +291,7 @@ bus_registry_ensure (BusRegistry               *registry,
     }
 
   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
-				       service->name, transaction, error))
+				       service->name, transaction, error, owner_connection_if_created))
     {
       bus_service_unref (service);
       return NULL;
diff --git a/bus/test.c b/bus/test.c
index 31ef4c8..3ca0952 100644
--- a/bus/test.c
+++ b/bus/test.c
@@ -216,12 +216,9 @@ bus_test_run_clients_loop (dbus_bool_t block_once)
   if (block_once)
     {
       _dbus_verbose ("---> blocking on \"client side\"\n");
-      _dbus_loop_iterate (client_loop, TRUE);
     }
 
   /* Then mop everything up */
-  while (_dbus_loop_iterate (client_loop, FALSE))
-    ;
 
   _dbus_verbose ("---> Done dispatching on \"client side\"\n");
 }
@@ -241,12 +238,9 @@ bus_test_run_bus_loop (BusContext *context,
   if (block_once)
     {
       _dbus_verbose ("---> blocking on \"server side\"\n");
-      _dbus_loop_iterate (bus_context_get_loop (context), TRUE);
     }
 
   /* Then mop everything up */
-  while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE))
-    ;
 
   _dbus_verbose ("---> Done dispatching on \"server side\"\n");
 }
@@ -254,9 +248,6 @@ bus_test_run_bus_loop (BusContext *context,
 void
 bus_test_run_everything (BusContext *context)
 {
-  while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE) ||
-         (client_loop == NULL || _dbus_loop_iterate (client_loop, FALSE)))
-    ;
 }
 
 BusContext*
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 81b3a83..ee50c91 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -255,6 +255,7 @@ static dbus_bool_t _dbus_modify_sigpipe = TRUE;
  */
 struct DBusConnection
 {
+  char autolaunched;
   DBusAtomic refcount; /**< Reference count. */
 
   DBusRMutex *mutex; /**< Lock on the entire DBusConnection */
@@ -598,6 +599,18 @@ dbus_connection_has_messages_to_send (DBusConnection *connection)
   return v;
 }
 
+static char
+dbus_connection_get_autolaunched (DBusConnection *connection)
+{
+   return connection->autolaunched;
+}
+
+static void
+dbus_connection_set_autolaunched (DBusConnection *connection)
+{
+   connection->autolaunched = 1;
+}
+
 /**
  * Gets the next outgoing message. The message remains in the
  * queue, and the caller does not own a reference to it.
@@ -1284,6 +1297,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
   connection = dbus_new0 (DBusConnection, 1);
   if (connection == NULL)
     goto error;
+  connection->autolaunched = 0;
 
   _dbus_rmutex_new_at_location (&connection->mutex);
   if (connection->mutex == NULL)
diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c
index f6736fe..f32cae9 100644
--- a/dbus/dbus-mainloop.c
+++ b/dbus/dbus-mainloop.c
@@ -22,6 +22,7 @@
  *
  */
 
+#include <bus/bus.h>
 #include <config.h>
 #include "dbus-mainloop.h"
 
@@ -31,25 +32,11 @@
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-socket-set.h>
 #include <dbus/dbus-watch.h>
+#include <dbus/dbus-server-protected.h>
 
 #define MAINLOOP_SPEW 0
 
-struct DBusLoop
-{
-  int refcount;
-  /** DBusPollable => dbus_malloc'd DBusList ** of references to DBusWatch */
-  DBusHashTable *watches;
-  DBusSocketSet *socket_set;
-  DBusList *timeouts;
-  int callback_list_serial;
-  int watch_count;
-  int timeout_count;
-  int depth; /**< number of recursive runs */
-  DBusList *need_dispatch;
-  /** TRUE if we will skip a watch next time because it was OOM; becomes
-   * FALSE between polling, and dealing with the results of the poll */
-  unsigned oom_watch_pending : 1;
-};
+#include <dbus/dbusloop.h>
 
 typedef struct
 {
@@ -563,9 +550,45 @@ _dbus_loop_queue_dispatch (DBusLoop       *loop,
  * descriptors, which is just used in test code as a debug hack
  */
 
+typedef struct BusContext
+{
+  int refcount;
+  DBusGUID uuid;
+  char *config_file;
+  char *type;
+  char *servicehelper;
+  char *address;
+  char *pidfile;
+  char *user;
+  char *log_prefix;
+  void *loop;
+  DBusList *servers;
+  void *connections;
+  void *activation;
+  void*registry;
+  void *policy;
+  void *matchmaker;
+  BusLimits limits;
+  unsigned int fork : 1;
+  unsigned int syslog : 1;
+  unsigned int keep_umask : 1;
+  unsigned int allow_anonymous : 1;
+  unsigned int systemd_activation : 1;
+} BusContext;
+
+
+typedef struct {
+    DBusSocketSet      parent;
+    void *fds;
+    int                n_fds;
+    int                n_reserved;
+    int                n_allocated;
+} _DBusSocketSetPoll;
+
 dbus_bool_t
 _dbus_loop_iterate (DBusLoop     *loop,
-                    dbus_bool_t   block)
+                    dbus_bool_t   block,
+                    void         *context)
 {  
 #define N_STACK_DESCRIPTORS 64
   dbus_bool_t retval;
@@ -655,6 +678,24 @@ _dbus_loop_iterate (DBusLoop     *loop,
   _dbus_verbose ("  polling on %d descriptors timeout %ld\n", _DBUS_N_ELEMENTS (ready_fds), timeout);
 #endif
 
+  int n_fds = ((_DBusSocketSetPoll*)loop->socket_set)->n_fds;
+
+  if(n_fds == 0 ||
+      /* idle timeout is over AND */
+      (loop->delaydone == 1 && (
+        /* only the dbus server is running */
+        (n_fds == 1) ||
+        /* only dbus services are running but no clients anymore */
+        ((DBusServer*)((BusContext*)context)->servers->data)->client_count -
+        ((DBusServer*)((BusContext*)context)->servers->data)->service_count == 0
+      )))
+  {
+     timeout = 0;
+     _dbus_loop_quit(loop);
+  } else { /* make sure to check back when the idle timeout is over */
+     timeout = idle_timeout;
+  }
+
   n_ready = _dbus_socket_set_poll (loop->socket_set, ready_fds,
                                    _DBUS_N_ELEMENTS (ready_fds), timeout);
 
@@ -865,7 +906,7 @@ _dbus_loop_iterate (DBusLoop     *loop,
 }
 
 void
-_dbus_loop_run (DBusLoop *loop)
+_dbus_loop_run (DBusLoop *loop, void *context)
 {
   int our_exit_depth;
 
@@ -880,7 +921,7 @@ _dbus_loop_run (DBusLoop *loop)
                  loop->depth - 1, loop->depth);
   
   while (loop->depth != our_exit_depth)
-    _dbus_loop_iterate (loop, TRUE);
+    _dbus_loop_iterate (loop, TRUE, context);
 
   _dbus_loop_unref (loop);
 }
diff --git a/dbus/dbus-mainloop.h b/dbus/dbus-mainloop.h
index a76cb6f..3e4cfb0 100644
--- a/dbus/dbus-mainloop.h
+++ b/dbus/dbus-mainloop.h
@@ -28,6 +28,7 @@
 
 #include <dbus/dbus.h>
 
+
 typedef struct DBusLoop DBusLoop;
 
 typedef dbus_bool_t (* DBusWatchFunction)   (DBusWatch     *watch,
@@ -51,10 +52,12 @@ void        _dbus_loop_remove_timeout (DBusLoop            *loop,
 dbus_bool_t _dbus_loop_queue_dispatch (DBusLoop            *loop,
                                        DBusConnection      *connection);
 
-void        _dbus_loop_run            (DBusLoop            *loop);
+void        _dbus_loop_run            (DBusLoop            *loop,
+                                       void                *context);
 void        _dbus_loop_quit           (DBusLoop            *loop);
 dbus_bool_t _dbus_loop_iterate        (DBusLoop            *loop,
-                                       dbus_bool_t          block);
+                                       dbus_bool_t          block,
+                                       void                *context);
 dbus_bool_t _dbus_loop_dispatch       (DBusLoop            *loop);
 
 int  _dbus_get_oom_wait    (void);
diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h
index f613bf3..342fd00 100644
--- a/dbus/dbus-server-protected.h
+++ b/dbus/dbus-server-protected.h
@@ -89,6 +89,11 @@ struct DBusServer
 #ifndef DBUS_DISABLE_CHECKS
   unsigned int have_server_lock : 1; /**< Does someone have the server mutex locked */
 #endif
+
+  int client_count; /* amount of connected clients to the server */
+  int service_count; /* amount of connected clients that are autolaunched services */
+
+  char delaydone;
 };
 
 dbus_bool_t _dbus_server_init_base      (DBusServer             *server,
diff --git a/dbus/dbus-server-socket.c b/dbus/dbus-server-socket.c
index d716f50..f80cb62 100644
--- a/dbus/dbus-server-socket.c
+++ b/dbus/dbus-server-socket.c
@@ -109,6 +109,7 @@ handle_new_client_fd_and_unlock (DBusServer *server,
       SERVER_UNLOCK (server);
       return FALSE;
     }
+  _dbus_transport_use_counter (transport, server);
 
   if (!_dbus_transport_set_auth_mechanisms (transport,
                                             (const char **) server->auth_mechanisms))
@@ -146,6 +147,8 @@ handle_new_client_fd_and_unlock (DBusServer *server,
       (* new_connection_function) (server, connection,
                                    new_connection_data);
     }
+  ++server->client_count;
+
   dbus_server_unref (server);
 
   /* If no one grabbed a reference, the connection will die. */
diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
index 9af906f..5cbfe6f 100644
--- a/dbus/dbus-server.c
+++ b/dbus/dbus-server.c
@@ -130,6 +130,8 @@ _dbus_server_init_base (DBusServer             *server,
   server->watches = NULL;
   server->timeouts = NULL;
   server->published_address = FALSE;
+  server->client_count = 0;
+  server->service_count = 0;
 
   if (!_dbus_string_init (&server->guid_hex))
     {
diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h
index bdbefa0..4871058 100644
--- a/dbus/dbus-server.h
+++ b/dbus/dbus-server.h
@@ -47,7 +47,6 @@ typedef struct DBusServer DBusServer;
 typedef void (* DBusNewConnectionFunction) (DBusServer     *server,
                                             DBusConnection *new_connection,
                                             void           *data);
-
 DBUS_EXPORT
 DBusServer* dbus_server_listen           (const char     *address,
                                           DBusError      *error);
diff --git a/dbus/dbus-socket-set.c b/dbus/dbus-socket-set.c
index 210d600..87e9486 100644
--- a/dbus/dbus-socket-set.c
+++ b/dbus/dbus-socket-set.c
@@ -31,6 +31,7 @@ _dbus_socket_set_new (int size_hint)
 {
   DBusSocketSet *ret;
 
+#undef DBUS_HAVE_LINUX_EPOLL
 #ifdef DBUS_HAVE_LINUX_EPOLL
   ret = _dbus_socket_set_epoll_new ();
 
diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h
index ee627a3..866ac40 100644
--- a/dbus/dbus-transport-protected.h
+++ b/dbus/dbus-transport-protected.h
@@ -30,6 +30,8 @@
 #include <dbus/dbus-auth.h>
 #include <dbus/dbus-resources.h>
 
+#include <dbus-server-protected.h>
+
 DBUS_BEGIN_DECLS
 
 typedef struct DBusTransportVTable DBusTransportVTable;
@@ -117,6 +119,7 @@ struct DBusTransport
   unsigned int is_server : 1;                 /**< #TRUE if on the server side */
   unsigned int unused_bytes_recovered : 1;    /**< #TRUE if we've recovered unused bytes from auth */
   unsigned int allow_anonymous : 1;           /**< #TRUE if an anonymous client can connect */
+  DBusServer *server;
 };
 
 dbus_bool_t _dbus_transport_init_base     (DBusTransport             *transport,
diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c
index 35c3cbf..8973001 100644
--- a/dbus/dbus-transport-socket.c
+++ b/dbus/dbus-transport-socket.c
@@ -22,6 +22,7 @@
  */
 
 #include <config.h>
+#include "dbus-connection.h"
 #include "dbus-internals.h"
 #include "dbus-connection-internal.h"
 #include "dbus-nonce.h"
@@ -29,6 +30,8 @@
 #include "dbus-transport-protected.h"
 #include "dbus-watch.h"
 #include "dbus-credentials.h"
+#include "dbus-hash.h"
+#include "dbus-object-tree.h"
 
 /**
  * @defgroup DBusTransportSocket DBusTransport implementations for sockets
@@ -1244,12 +1247,40 @@ socket_get_socket_fd (DBusTransport *transport,
                       DBusSocket    *fd_p)
 {
   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
-  
+
   *fd_p = socket_transport->fd;
-  
+
   return TRUE;
 }
 
+struct DBusConnection
+{
+  char autolaunched;
+};
+
+static void
+socket_disconnect_with_counter (DBusTransport *transport)
+{
+  socket_disconnect(transport);
+  --transport->server->client_count;
+  if(transport->connection->autolaunched)
+    --transport->server->service_count;
+  if(transport->server->delaydone == 1 &&
+     transport->server->client_count - transport->server->service_count == 0)
+    transport->server->vtable->disconnect(transport->server);
+}
+
+static const DBusTransportVTable socket_vtable_with_counter = {
+  socket_finalize,
+  socket_handle_watch,
+  socket_disconnect_with_counter,
+  socket_connection_set,
+  socket_do_iteration,
+  socket_live_messages_changed,
+  socket_get_socket_fd
+};
+
+
 static const DBusTransportVTable socket_vtable = {
   socket_finalize,
   socket_handle_watch,
@@ -1260,6 +1291,13 @@ static const DBusTransportVTable socket_vtable = {
   socket_get_socket_fd
 };
 
+void
+_dbus_transport_use_counter (DBusTransport *transport, DBusServer *server)
+{
+  transport->server = server;
+  transport->vtable = &socket_vtable_with_counter;
+}
+
 /**
  * Creates a new transport for the given socket file descriptor.  The file
  * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
diff --git a/dbus/dbus-transport-socket.h b/dbus/dbus-transport-socket.h
index b8267ff..32b8ea9 100644
--- a/dbus/dbus-transport-socket.h
+++ b/dbus/dbus-transport-socket.h
@@ -39,6 +39,8 @@ DBusTransportOpenResult _dbus_transport_open_socket        (DBusAddressEntry  *e
                                                             DBusTransport    **transport_p,
                                                             DBusError         *error);
 
+void                    _dbus_transport_use_counter        (DBusTransport     *transport,
+                                                            DBusServer        *server);
 
 
 DBUS_END_DECLS
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index 31586b1..fd8f6ec 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -246,8 +246,8 @@ _dbus_transport_finalize_base (DBusTransport *transport)
  * @param error address where an error can be returned.
  * @returns a new transport, or #NULL on failure.
  */
-static DBusTransport*
-check_address (const char *address, DBusError *error)
+DBusTransport*
+_dbus_check_address (const char *address, DBusError *error)
 {
   DBusAddressEntry **entries;
   DBusTransport *transport = NULL;
@@ -297,7 +297,7 @@ _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
       goto out;
     }
 
-  result = check_address (_dbus_string_get_const_data (&address), error);
+  result = _dbus_check_address (_dbus_string_get_const_data (&address), error);
   if (result == NULL)
     _DBUS_ASSERT_ERROR_IS_SET (error);
   else
diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h
index 9e3787d..e385458 100644
--- a/dbus/dbus-transport.h
+++ b/dbus/dbus-transport.h
@@ -34,6 +34,10 @@ typedef struct DBusTransport DBusTransport;
 
 DBusTransport*     _dbus_transport_open                   (DBusAddressEntry           *entry,
                                                            DBusError                  *error);
+void               _dbus_transport_finalize_base          (DBusTransport              *transport);
+
+DBusTransport*     _dbus_check_address                    (const char                 *address,
+                                                           DBusError *error);
 DBusTransport*     _dbus_transport_ref                    (DBusTransport              *transport);
 void               _dbus_transport_unref                  (DBusTransport              *transport);
 void               _dbus_transport_disconnect             (DBusTransport              *transport);
diff --git a/dbus/dbusloop.h b/dbus/dbusloop.h
new file mode 100644
index 0000000..52b3b9a
--- /dev/null
+++ b/dbus/dbusloop.h
@@ -0,0 +1,18 @@
+#include <dbus/dbus-socket-set.h>
+struct DBusLoop
+{
+  int refcount;
+  /** DBusPollable => dbus_malloc'd DBusList ** of references to DBusWatch */
+  DBusHashTable *watches;
+  DBusSocketSet *socket_set;
+  DBusList *timeouts;
+  int callback_list_serial;
+  int watch_count;
+  int timeout_count;
+  int depth; /**< number of recursive runs */
+  DBusList *need_dispatch;
+  /** TRUE if we will skip a watch next time because it was OOM; becomes
+   * FALSE between polling, and dealing with the results of the poll */
+  unsigned oom_watch_pending : 1;
+  char delaydone;
+};
diff --git a/debian/dbus-tests.install b/debian/dbus-tests.install
deleted file mode 100644
index 2a73f98..0000000
--- a/debian/dbus-tests.install
+++ /dev/null
@@ -1,4 +0,0 @@
-debian/tmp/usr/bin/dbus-test-tool
-debian/tmp/usr/share/man/man1/dbus-test-tool.1
-debian/tmp/usr/share/installed-tests/dbus
-debian/tmp/usr/lib/dbus-1.0/installed-tests
diff --git a/debian/dbus-tests.lintian-overrides b/debian/dbus-tests.lintian-overrides
deleted file mode 100644
index dfb9804..0000000
--- a/debian/dbus-tests.lintian-overrides
+++ /dev/null
@@ -1,2 +0,0 @@
-# false positive: we only say dbus when talking about an executable
-dbus-tests: capitalization-error-in-description dbus D-Bus
diff --git a/debian/rules b/debian/rules
index 3cb4b0e..761542e 100755
--- a/debian/rules
+++ b/debian/rules
@@ -35,7 +35,7 @@ endif
 common_configure_flags := \
 		--disable-ducktype-docs \
 		--disable-silent-rules \
-		--enable-installed-tests \
+		--disable-installed-tests \
 		--libexecdir=\$${prefix}/lib/dbus-1.0 \
 		$(NULL)
 
@@ -110,7 +110,7 @@ endif
 ifeq ($(filter stage1,$(DEB_BUILD_PROFILES)),)
 # not a stage1 build - build all the tests
 debug_configure_flags += \
-		--enable-tests \
+		--disable-tests \
 		$(NULL)
 endif
 
@@ -170,8 +170,6 @@ endif
 	rm -rfv debian/tmp/${debug_build_prefix}/share/dbus-1/system-services
 	rm -rfv debian/tmp/${debug_build_prefix}/share/doc
 	rm -rfv debian/tmp/${debug_build_prefix}/share/man
-	mv debian/tmp/${debug_build_prefix}/share/installed-tests/dbus \
-		debian/tmp/${debug_build_prefix}/share/installed-tests/dbus-debug-build
 	rm -f debian/tmp/${debug_build_prefix}/lib/libdbus-1.la
 	cd $(CURDIR)/debian/tmp && find | LC_ALL=C sort
 	# normal build (do this last so that it overwrites the others)
@@ -193,8 +191,6 @@ override_dh_link:
 # the directory in case that's happened, so the .install file doesn't need
 # modification
 override_dh_install:
-	install -d debian/tmp/usr/lib/dbus-1.0/installed-tests/dbus
-	install -d debian/tmp/${debug_build_prefix}/lib/dbus-1.0/installed-tests/dbus
 	dh_install -p$(libdbusN) \
 		"usr/lib/$(DEB_HOST_MULTIARCH)/$(libdbus_soname)*" \
 		lib/$(DEB_HOST_MULTIARCH)
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 56a0b7f..749e42a 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -57,8 +57,8 @@ dbus_launch_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	$(NULL)
 dbus_launch_LDADD = \
-	$(top_builddir)/dbus/libdbus-1.la \
-	$(DBUS_X_LIBS) \
+	$(top_builddir)/dbus/.libs/libdbus-1.a \
+	$(DBUS_X_LIBS) $(SYSTEMD_LIBS) -lpthread \
 	$(NULL)
 
 dbus_run_session_SOURCES =			\
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.