hal/hald hald_dbus.c,1.55,1.56

David Zeuthen david at freedesktop.org
Tue Feb 14 01:14:19 PST 2006


Update of /cvs/hal/hal/hald
In directory gabe:/tmp/cvs-serv17318/hald

Modified Files:
	hald_dbus.c 
Log Message:
2006-02-14  David Zeuthen  <davidz at redhat.com>

        * hald/hald_dbus.c (hald_exec_method_do_invocation)
        (hald_exec_method_enqueue, hald_exec_method_process_queue)
        (hald_exec_method_cb, hald_exec_method): To avoid a race of
        several processes invoking methods at the same time we now
        maintain a queue of method calls per-device. One very real example
        of this is gnome-mount when setting up crypto devices; after
        Crypto.Setup() gnome-mount waits for the cleartext block device
        and attempts to mount it; meanwhile g-v-m sees the cleartext block
        device too and attempts to mount too. Since mounting is a
        relatively slow operation both methods are executed at the same
        time and we end up with two mounts. This patch fixes this problem.



Index: hald_dbus.c
===================================================================
RCS file: /cvs/hal/hal/hald/hald_dbus.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- hald_dbus.c	14 Feb 2006 02:52:44 -0000	1.55
+++ hald_dbus.c	14 Feb 2006 09:14:16 -0000	1.56
@@ -2528,6 +2528,102 @@
 	return DBUS_HANDLER_RESULT_HANDLED;
 }
 
+typedef struct {
+	char *udi;
+	char *execpath;
+	char **extra_env;
+	char *stdin;
+	DBusMessage *message;
+	DBusConnection *connection;
+} MethodInvocation;
+
+static void
+hald_exec_method_cb (HalDevice *d, guint32 exit_type, 
+		     gint return_code, gchar **error,
+		     gpointer data1, gpointer data2);
+
+static void
+hald_exec_method_do_invocation (MethodInvocation *mi)
+{
+	HalDevice *d;
+
+	d = hal_device_store_find (hald_get_gdl (), mi->udi);
+	if (d == NULL)
+		d = hal_device_store_find (hald_get_tdl (), mi->udi);
+
+	if (d != NULL) {
+		/* no timeout */
+		hald_runner_run_method(d, 
+				       mi->execpath, 
+				       mi->extra_env, 
+				       mi->stdin, 
+				       TRUE,
+				       0,
+				       hald_exec_method_cb,
+				       (gpointer) mi->message, 
+				       (gpointer) mi->connection);
+	} else {
+		HAL_WARNING (("In-queue method call on non-existant device"));
+	}
+
+	g_free (mi->udi);
+	g_free (mi->execpath);
+	g_strfreev (mi->extra_env);
+	g_free (mi->stdin);
+	g_free (mi);
+}
+
+
+static GHashTable *udi_to_method_queue = NULL;
+
+static void
+hald_exec_method_enqueue (MethodInvocation *mi)
+{
+	gpointer origkey;
+	GList *queue;
+
+	if (udi_to_method_queue == NULL) {
+		udi_to_method_queue = g_hash_table_new (g_str_hash,
+							g_str_equal);
+	}
+
+	if (g_hash_table_lookup_extended (udi_to_method_queue, mi->udi, &origkey, (gpointer) &queue)) {
+		HAL_INFO (("enqueue"));;
+		queue = g_list_append (queue, mi);
+		g_hash_table_replace (udi_to_method_queue, g_strdup (mi->udi), queue);
+	} else {
+		HAL_INFO (("no need to enqueue"));;
+		queue = g_list_append (NULL, mi);
+		g_hash_table_insert (udi_to_method_queue, g_strdup (mi->udi), queue);
+
+		hald_exec_method_do_invocation (mi);
+	}
+}
+
+
+static void 
+hald_exec_method_process_queue (const char *udi)
+{
+	gpointer origkey;
+	GList *queue;
+
+	if (g_hash_table_lookup_extended (udi_to_method_queue, udi, &origkey, (gpointer) &queue)) {
+		if (queue != NULL) {
+			queue = g_list_delete_link (queue, queue);
+		}
+
+		if (queue == NULL) {
+			HAL_INFO (("No more methods in queue"));;
+			g_hash_table_remove (udi_to_method_queue, udi);
+		} else {
+			HAL_INFO (("Execing next method in queue"));;
+			g_hash_table_replace (udi_to_method_queue, g_strdup (udi), queue);
+
+			hald_exec_method_do_invocation ((MethodInvocation *) queue->data);
+		}
+	}
+}
+
 static void
 hald_exec_method_cb (HalDevice *d, guint32 exit_type, 
 		     gint return_code, gchar **error,
@@ -2541,6 +2637,8 @@
 	gchar *exp_name = NULL;
 	gchar *exp_detail = NULL;
 
+	hald_exec_method_process_queue (d->udi);
+
 	message = (DBusMessage *) data1;
 	conn = (DBusConnection *) data2;
 	
@@ -2605,6 +2703,7 @@
 	DBusMessageIter iter;
 	char *extra_env[2];
 	char uid_export[128];
+	MethodInvocation *mi;
 
 	/* add calling uid */
 	extra_env[0] = NULL;
@@ -2729,13 +2828,15 @@
 		dbus_message_iter_next (&iter);
 	}
 
-	/* no timeout */
-	hald_runner_run_method(d, 
-			       execpath, extra_env, 
-			       stdin_str->str, TRUE,
-			       0,
-			       hald_exec_method_cb,
-			       (gpointer) message, (gpointer) connection);
+	mi = g_new0 (MethodInvocation, 1);
+	mi->udi = g_strdup (d->udi);
+	mi->execpath = g_strdup (execpath);
+	mi->extra_env = g_strdupv (extra_env);
+	mi->stdin = g_strdup (stdin_str->str);
+	mi->message = message;
+	mi->connection = connection;
+	hald_exec_method_enqueue (mi);
+
 	dbus_message_ref (message);
 	g_string_free (stdin_str, TRUE);
 




More information about the hal-commit mailing list