[PATCH] Handle case when autolaunched daemon address is already published on windows.

Ralf Habacker ralf.habacker at freenet.de
Mon Dec 13 23:12:59 PST 2010


---
 dbus/dbus-server-protected.h |    3 +-
 dbus/dbus-server-win.c       |    6 +++-
 dbus/dbus-server.c           |   10 ++++++
 dbus/dbus-sysdeps-win.c      |   65 +++++++++++++++++++++++++++++++++--------
 dbus/dbus-sysdeps.h          |    4 ++-
 5 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h
index 9e759c1..31976e3 100644
--- a/dbus/dbus-server-protected.h
+++ b/dbus/dbus-server-protected.h
@@ -118,7 +118,8 @@ typedef enum
   DBUS_SERVER_LISTEN_NOT_HANDLED, /**< we aren't in charge of this address type */
   DBUS_SERVER_LISTEN_OK,          /**< we set up the listen */
   DBUS_SERVER_LISTEN_BAD_ADDRESS, /**< malformed address */
-  DBUS_SERVER_LISTEN_DID_NOT_CONNECT /**< well-formed address but failed to set it up */
+  DBUS_SERVER_LISTEN_DID_NOT_CONNECT, /**< well-formed address but failed to set it up */
+  DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED /**< address is already used */
 } DBusServerListenResult;
 
 DBusServerListenResult _dbus_server_listen_platform_specific (DBusAddressEntry  *entry,
diff --git a/dbus/dbus-server-win.c b/dbus/dbus-server-win.c
index 860978d..bf1c896 100644
--- a/dbus/dbus-server-win.c
+++ b/dbus/dbus-server-win.c
@@ -91,18 +91,22 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
       const char *family = "ipv4";
       const char *scope = dbus_address_entry_get_value (entry, "scope");
 
+      if (_dbus_daemon_is_session_bus_address_published (scope))
+          return DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED;
+
       *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
                                                    family, error, FALSE);
       if (*server_p)
         {
           _DBUS_ASSERT_ERROR_IS_CLEAR(error);
-          /// @todo should we return an error when address could not be published ?
           (*server_p)->published_address =
               _dbus_daemon_publish_session_bus_address ((*server_p)->address, scope);
           return DBUS_SERVER_LISTEN_OK;
         }
       else
         {
+          // make sure no handle is open
+          _dbus_daemon_unpublish_session_bus_address ();
           _DBUS_ASSERT_ERROR_IS_SET(error);
           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
         }
diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
index 91fdcb6..60d14b3 100644
--- a/dbus/dbus-server.c
+++ b/dbus/dbus-server.c
@@ -577,6 +577,16 @@ dbus_server_listen (const char     *address,
               handled_once = TRUE;
               goto out;
             }
+          else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
+            {
+              _dbus_assert (server == NULL);
+              dbus_set_error (error,
+                       DBUS_ERROR_ADDRESS_IN_USE,
+                       "Address '%s' already used",
+                       dbus_address_entry_get_method (entries[0]));
+              handled_once = TRUE;
+              goto out;
+            }
           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
             {
               _dbus_assert (server == NULL);
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index bacfcb2..024a833 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -4,9 +4,9 @@
  * Copyright (C) 2002, 2003  Red Hat, Inc.
  * Copyright (C) 2003 CodeFactory AB
  * Copyright (C) 2005 Novell, Inc.
- * Copyright (C) 2006 Ralf Habacker <ralf.habacker at freenet.de>
  * Copyright (C) 2006 Peter Kümmel  <syntheticpp at gmx.net>
  * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher at gmx.de>
+ * Copyright (C) 2006-2010 Ralf Habacker <ralf.habacker at freenet.de>
  *
  * Licensed under the Academic Free License version 2.1
  * 
@@ -2623,6 +2623,48 @@ _dbus_get_mutex_name (DBusString *out,const char *scope)
 }
 
 dbus_bool_t
+_dbus_daemon_is_session_bus_address_published (const char *scope)
+{
+  HANDLE lock;
+  HANDLE mutex;
+  DBusString mutex_name;
+  DWORD ret;
+
+  if (!_dbus_get_mutex_name(&mutex_name,scope))
+    {
+      _dbus_string_free( &mutex_name );
+      return FALSE;
+    }
+
+  if (hDBusDaemonMutex)
+      return TRUE;
+
+  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+  lock = _dbus_global_lock( cUniqueDBusInitMutex );
+
+  // we use CreateMutex instead of OpenMutex because of possible race conditions,
+  // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx
+  hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
+
+  _dbus_global_unlock( lock );
+
+  _dbus_string_free( &mutex_name );
+
+  if (hDBusDaemonMutex  == NULL)
+      return FALSE;
+  if (GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      CloseHandle(hDBusDaemonMutex);
+      hDBusDaemonMutex = NULL;
+      return TRUE;
+    }
+  // mutex wasn't created before, so return false.
+  // We leave the mutex name allocated for later reusage
+  // in _dbus_daemon_publish_session_bus_address.
+  return FALSE;
+}
+
+dbus_bool_t
 _dbus_daemon_publish_session_bus_address (const char* address, const char *scope)
 {
   HANDLE lock;
@@ -2640,24 +2682,22 @@ _dbus_daemon_publish_session_bus_address (const char* address, const char *scope
       return FALSE;
     }
 
-  // before _dbus_global_lock to keep correct lock/release order
-  hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
-  ret = WaitForSingleObject( hDBusDaemonMutex, 1000 );
-  if ( ret != WAIT_OBJECT_0 ) {
-    _dbus_warn("Could not lock mutex %s (return code %d). daemon already running? Bus address not published.\n", _dbus_string_get_const_data(&mutex_name), ret );
-    return FALSE;
-  }
+  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+  lock = _dbus_global_lock( cUniqueDBusInitMutex );
+
+  if (!hDBusDaemonMutex)
+    {
+      hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
+    }
+  _dbus_string_free( &mutex_name );
 
   if (!_dbus_get_shm_name(&shm_name,scope))
     {
-      _dbus_string_free( &mutex_name );
       _dbus_string_free( &shm_name );
+      _dbus_global_unlock( lock );
       return FALSE;
     }
 
-  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
-  lock = _dbus_global_lock( cUniqueDBusInitMutex );
-
   // create shm
   hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
                                        0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) );
@@ -2676,7 +2716,6 @@ _dbus_daemon_publish_session_bus_address (const char* address, const char *scope
   _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) );
 
   _dbus_string_free( &shm_name );
-  _dbus_string_free( &mutex_name );
   return TRUE;
 }
 
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index a0f62ee..eb91957 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -207,7 +207,9 @@ dbus_bool_t _dbus_windows_user_is_process_owner (const char        *windows_sid)
 dbus_bool_t _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
                                                             DBusCredentials *credentials);
 
-dbus_bool_t _dbus_daemon_publish_session_bus_address (const char* address, const char* shm_address);
+dbus_bool_t _dbus_daemon_is_session_bus_address_published (const char *scope);
+
+dbus_bool_t _dbus_daemon_publish_session_bus_address (const char* address, const char* shm_name);
 
 void _dbus_daemon_unpublish_session_bus_address (void);
 
-- 
1.5.6.5


--------------040108060009030807070208--


More information about the dbus mailing list