From 481261897f076dbfa74a68dcab7b76c6c769abdd Mon Sep 17 00:00:00 2001 From: Ralf Habacker Date: Tue, 11 Apr 2017 11:17:40 +0200 Subject: [PATCH] Add support for auto shutdown dbus-daemon after last client disconnects on Windows. By default dbus-daemon on Windows is auto started on request by any dbus client application and now also shutdown itself after the last client has been disconnected to free unused system resources and simplifies portable installations. The auto shutting down behavior could be disabled by specifing --disable-auto-shutdown on dbus-daemon command line. https://bugs.freedesktop.org/show_bug.cgi?id=99751 --- bus/bus.c | 30 ++++++++++++++++++++++++++++++ bus/bus.h | 6 ++++++ bus/connection.c | 28 +++++++++++++++++++++++++++- bus/main.c | 19 +++++++++++++++++++ dbus/dbus-sysdeps-unix.c | 6 ++++++ dbus/dbus-sysdeps-win.c | 28 +++++++++++++++++++++++++--- dbus/dbus-sysdeps.h | 2 ++ doc/dbus-daemon.1.xml.in | 10 ++++++++++ 8 files changed, 125 insertions(+), 4 deletions(-) diff --git a/bus/bus.c b/bus/bus.c index b013866..3b2287a 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -74,6 +74,8 @@ struct BusContext unsigned int allow_anonymous : 1; unsigned int systemd_activation : 1; dbus_bool_t watches_enabled; + int n_connections; + dbus_bool_t auto_shutdown_enabled; }; static dbus_int32_t server_data_slot = -1; @@ -1825,3 +1827,31 @@ bus_context_check_all_watches (BusContext *context) _dbus_server_toggle_all_watches (server, enabled); } } + +void bus_context_increment_connections (BusContext *context) +{ + context->n_connections++; +} + +void +bus_context_decrement_connections (BusContext *context) +{ + context->n_connections--; +} + +int bus_context_n_connections (BusContext *context) +{ + return context->n_connections; +} + +dbus_bool_t +bus_context_get_auto_shutdown_enabled (BusContext *context) +{ + return context->auto_shutdown_enabled; +} + +void +bus_context_set_auto_shutdown_enabled (BusContext *context, dbus_bool_t state) +{ + context->auto_shutdown_enabled = state; +} diff --git a/bus/bus.h b/bus/bus.h index 2e0de82..9972b6c 100644 --- a/bus/bus.h +++ b/bus/bus.h @@ -145,5 +145,11 @@ dbus_bool_t bus_context_check_security_policy (BusContext BusActivationEntry *activation_entry, DBusError *error); void bus_context_check_all_watches (BusContext *context); +void bus_context_increment_connections (BusContext *context); +void bus_context_decrement_connections (BusContext *context); +int bus_context_n_connections (BusContext *context); +dbus_bool_t bus_context_get_auto_shutdown_enabled (BusContext *context); +void bus_context_set_auto_shutdown_enabled (BusContext *context, + dbus_bool_t state); #endif /* BUS_BUS_H */ diff --git a/bus/connection.c b/bus/connection.c index 5144218..aab7f69 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -295,6 +295,29 @@ bus_connection_disconnected (DBusConnection *connection) bus_connection_remove_transactions (connection); + bus_context_decrement_connections (d->connections->context); + _dbus_verbose ("decrement number of connection %d\n", bus_context_n_connections (d->connections->context)); + if (bus_context_n_connections (d->connections->context) == 0) + { + const char *s = bus_context_get_address (d->connections->context); + if (bus_context_get_auto_shutdown_enabled (d->connections->context)) + { + if (_dbus_daemon_lock_autolaunch_address ()) + { + DBusLoop *loop = bus_context_get_loop (d->connections->context); + _dbus_loop_quit (loop); + _dbus_verbose ("Got auto shutdown request - quit event loop\n"); + } + else + { + // We are not able to lock autolaunch address mutex because a + // dbus client tries to fetch autolaunch address as part of the + // autolaunch connection attempt + _dbus_verbose ("Could not lock autolaunch address - skipping shutdown"); + } + } + } + if (d->link_in_monitors != NULL) { BusMatchmaker *mm = d->connections->monitor_matchmaker; @@ -1582,7 +1605,10 @@ bus_connection_complete (DBusConnection *connection, d->name = NULL; return FALSE; } - + + bus_context_increment_connections (d->connections->context); + _dbus_verbose ("increment number of connection %d\n", bus_context_n_connections (d->connections->context)); + if (dbus_connection_get_unix_user (connection, &uid)) { if (!adjust_connections_for_uid (d->connections, diff --git a/bus/main.c b/bus/main.c index 17750ef..9f2890f 100644 --- a/bus/main.c +++ b/bus/main.c @@ -157,6 +157,9 @@ usage (void) " [--syslog]" " [--syslog-only]" " [--nofork]" +#ifdef DBUS_WIN + " [--disable-auto-shutdown]" +#endif #ifdef DBUS_UNIX " [--fork]" " [--systemd-activation]" @@ -395,6 +398,9 @@ main (int argc, char **argv) int i; dbus_bool_t print_address; dbus_bool_t print_pid; +#ifdef DBUS_WIN + dbus_bool_t auto_shutdown; +#endif BusContextFlags flags; #ifdef DBUS_UNIX const char *error_str; @@ -432,6 +438,9 @@ main (int argc, char **argv) print_address = FALSE; print_pid = FALSE; +#ifdef DBUS_WIN + auto_shutdown = TRUE; +#endif flags = BUS_CONTEXT_FLAG_WRITE_PID_FILE; @@ -608,6 +617,12 @@ main (int argc, char **argv) { print_pid = TRUE; /* and we'll get the next arg if appropriate */ } +#ifdef DBUS_WIW + else if (strcmp (arg, "--disable-auto-shutdown") == 0) + { + auto_shutdown = FALSE; + } +#endif else { usage (); @@ -694,6 +709,10 @@ main (int argc, char **argv) exit (1); } +#ifdef DBUS_WIN + if (auto_shutdown) + bus_context_set_auto_shutdown_enabled (context, TRUE); +#endif /* bus_context_new() closes the print_addr_pipe and * print_pid_pipe */ diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 8b6ac30..83613df 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -4271,6 +4271,12 @@ _dbus_daemon_publish_session_bus_address (const char* addr, return TRUE; } +dbus_bool_t +_dbus_daemon_lock_autolaunch_address () +{ + return FALSE; +} + //PENDING(kdab) docs void _dbus_daemon_unpublish_session_bus_address (void) diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 5a94eaf..b15b13f 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -2859,6 +2859,25 @@ _dbus_daemon_is_session_bus_address_published (const char *scope) return FALSE; } +/** + * Lock access to autolaunched address + * + * This function is called to prevent client from accessing + * autolaunch address in shared memory segment as preparation + * to shutdown server + * @return TRUE lock has been gotten + * @return FALSE lock has not been gotten + */ +dbus_bool_t +_dbus_daemon_lock_autolaunch_address () +{ + HANDLE lock; + + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address, + // _dbus_daemon_already_runs and _dbus_daemon_lock_autolaunch_address + return _dbus_global_lock (cUniqueDBusInitMutex) != FALSE; +} + dbus_bool_t _dbus_daemon_publish_session_bus_address (const char* address, const char *scope) { @@ -2876,7 +2895,8 @@ _dbus_daemon_publish_session_bus_address (const char* address, const char *scope return FALSE; } - // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address, + // _dbus_daemon_already_runs and _dbus_daemon_lock_autolaunch_address lock = _dbus_global_lock( cUniqueDBusInitMutex ); if (!hDBusDaemonMutex) @@ -2929,7 +2949,8 @@ _dbus_daemon_unpublish_session_bus_address (void) { HANDLE lock; - // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address, + // _dbus_daemon_already_runs and _dbus_daemon_lock_autolaunch_address lock = _dbus_global_lock( cUniqueDBusInitMutex ); CloseHandle( hDBusSharedMem ); @@ -2996,7 +3017,8 @@ _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char return FALSE; } - // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address, + // _dbus_daemon_already_runs and _dbus_daemon_lock_autolaunch_address lock = _dbus_global_lock( cUniqueDBusInitMutex ); // do checks diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 5ed4c45..13ac680 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -610,6 +610,8 @@ void _dbus_logv (DBusSystemLogSeverity severity, _DBUS_BYTE_OF_PRIMITIVE (a, 6) == _DBUS_BYTE_OF_PRIMITIVE (b, 6) && \ _DBUS_BYTE_OF_PRIMITIVE (a, 7) == _DBUS_BYTE_OF_PRIMITIVE (b, 7)) +DBUS_PRIVATE_EXPORT +dbus_bool_t _dbus_daemon_lock_autolaunch_address(); dbus_bool_t _dbus_get_autolaunch_address (const char *scope, DBusString *address, DBusError *error); diff --git a/doc/dbus-daemon.1.xml.in b/doc/dbus-daemon.1.xml.in index a9a46ee..7d37870 100644 --- a/doc/dbus-daemon.1.xml.in +++ b/doc/dbus-daemon.1.xml.in @@ -32,6 +32,7 @@ --nosyslog --syslog --syslog-only + --disable-auto-shutdown @@ -197,6 +198,15 @@ files. + + + + On Windows dbus daemon is autolaunched by dbus client library if an + autolaunch bus address is specified. After last client disconnects it + shuts down by default if not disabled with this switch. + + + -- 1.8.4.5