[PATCH 1/6] add hald-runner support for singleton addons

Rob Taylor rob.taylor at codethink.co.uk
Thu Jun 7 03:52:55 PDT 2007


Introduces a new method StartSingleton on org.freedesktop.HalRunner.  This
takes one parameter of an array of strings for the environment to launch the
singleton. hald-runner keeps a list of running singletons, which are killable
only by KillAll.

The patch also adds hald_runner_start_singleton for starting a singleton.
---
 hald-runner/main.c   |   51 +++++++++++++++++++++++++++------
 hald-runner/runner.c |   37 +++++++++++++++--------
 hald-runner/runner.h |    1 +
 hald/hald_runner.c   |   78 +++++++++++++++++++++++++++++++++++++------------
 hald/hald_runner.h   |    6 ++++
 5 files changed, 132 insertions(+), 41 deletions(-)

diff --git a/hald-runner/main.c b/hald-runner/main.c
index 3b170b3..f767b9b 100644
--- a/hald-runner/main.c
+++ b/hald-runner/main.c
@@ -4,6 +4,7 @@
  * main.c - Main dbus interface of the hald runner
  *
  * Copyright (C) 2006 Sjoerd Simons, <sjoerd at luon.net>
+ * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor at codethink.co.uk>
  *
  * Licensed under the Academic Free License version 2.1
  *
@@ -36,19 +37,33 @@
 #endif
 
 static gboolean
-parse_first_part(run_request *r, DBusMessage *msg, DBusMessageIter *iter)
+parse_udi (run_request *r, DBusMessage *msg, DBusMessageIter *iter)
 {
-	DBusMessageIter sub_iter;
 	char *tmpstr;
 
-	/* First should be the device UDI */
+	/* Should be the device UDI */
 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) 
 		goto malformed;
 	dbus_message_iter_get_basic(iter, &tmpstr);
 	r->udi = g_strdup(tmpstr);
 
-	/* Then the environment array */
-	if (!dbus_message_iter_next(iter) || dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+	if (!dbus_message_iter_next(iter))
+		goto malformed;
+
+	return TRUE;
+
+malformed:
+	return FALSE;
+}
+
+static gboolean
+parse_environment(run_request *r, DBusMessage *msg, DBusMessageIter *iter)
+{
+	DBusMessageIter sub_iter;
+	char *tmpstr;
+
+	/* The environment array */
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
 		goto malformed;
 	dbus_message_iter_recurse(iter, &sub_iter);
 	/* Add default path for the programs we start */
@@ -82,7 +97,10 @@ handle_run(DBusConnection *con, DBusMessage *msg)
 	r = new_run_request();
 	g_assert(dbus_message_iter_init(msg, &iter));
 
-	if (!parse_first_part(r, msg, &iter)) 
+	if (!parse_udi(r, msg, &iter))
+		goto malformed;
+
+	if (!parse_environment(r, msg, &iter))
 		goto malformed;
 
 	/* Next a string of what should be written to stdin */
@@ -114,7 +132,7 @@ malformed:
 }
 
 static void
-handle_start(DBusConnection *con, DBusMessage *msg)
+handle_start(DBusConnection *con, DBusMessage *msg, gboolean is_singleton)
 {
 	DBusMessage *reply;
 	DBusMessageIter iter;
@@ -122,10 +140,22 @@ handle_start(DBusConnection *con, DBusMessage *msg)
 	GPid pid __attribute__ ((aligned));
 
 	r = new_run_request();
+	r->is_singleton = is_singleton;
+
 	g_assert(dbus_message_iter_init(msg, &iter));
 
-	if (!dbus_message_iter_init(msg, &iter) || !parse_first_part(r, msg, &iter))
+	if (!dbus_message_iter_init(msg, &iter))
+		goto malformed;
+
+	if (!is_singleton && !parse_udi(r, msg, &iter)) {
+		fprintf(stderr, "error parsing udi");
+		goto malformed;
+	}
+
+	if (!parse_environment(r, msg, &iter)) {
+		fprintf(stderr, "error parsing environment");
 		goto malformed;
+	}
 
 	if (run_request_run(r, con, NULL, &pid)) {
 		reply = dbus_message_new_method_return(msg);
@@ -183,7 +213,10 @@ filter(DBusConnection *con, DBusMessage *msg, void *user_data)
 		handle_run(con, msg);
 		return DBUS_HANDLER_RESULT_HANDLED;
 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Start")) {
-		handle_start(con, msg);
+		handle_start(con, msg, FALSE);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "StartSingleton")) {
+		handle_start(con, msg, TRUE);
 		return DBUS_HANDLER_RESULT_HANDLED;
 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Kill")) {
 		handle_kill(con, msg);
diff --git a/hald-runner/runner.c b/hald-runner/runner.c
index 57a2a80..cd6cf82 100644
--- a/hald-runner/runner.c
+++ b/hald-runner/runner.c
@@ -4,6 +4,7 @@
  * runner.c - Process running code
  *
  * Copyright (C) 2006 Sjoerd Simons, <sjoerd at luon.net>
+ * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor at codethink.co.uk>
  *
  * Licensed under the Academic Free License version 2.1
  *
@@ -48,6 +49,7 @@
 #define HALD_RUN_KILLED 0x4
 
 GHashTable *udi_hash = NULL;
+GList *singletons = NULL;
 
 typedef struct {
 	run_request *r;
@@ -128,15 +130,19 @@ send_reply(DBusConnection *con, DBusMessage *msg, guint32 exit_type, gint32 retu
 }
 
 static void
-remove_from_hash_table(run_data *rd)
+remove_run_data(run_data *rd)
 {
 	GList *list;
 
-	/* Remove to the hashtable */
-	list = (GList *)g_hash_table_lookup(udi_hash, rd->r->udi);
-	list = g_list_remove(list, rd);
-	/* The hash table will take care to not leak the dupped string */
-	g_hash_table_insert(udi_hash, g_strdup(rd->r->udi), list);
+	if (rd->r->is_singleton) {
+		singletons = g_list_remove(singletons, rd);
+	} else {
+		/* Remove to the hashtable */
+		list = (GList *)g_hash_table_lookup(udi_hash, rd->r->udi);
+		list = g_list_remove(list, rd);
+		/* The hash table will take care to not leak the dupped string */
+		g_hash_table_insert(udi_hash, g_strdup(rd->r->udi), list);
+	}
 }
 
 static void
@@ -170,7 +176,7 @@ run_exited(GPid pid, gint status, gpointer data)
 	free_string_array(error);
 
 out:
-	remove_from_hash_table(rd);
+	remove_run_data (rd);
 		
 	/* emit a signal that this PID exited */
 	if(rd->con != NULL && rd->emit_pid_exited) {
@@ -200,7 +206,7 @@ run_timedout(gpointer data) {
 	rd->sent_kill = TRUE;
 
 	send_reply(rd->con, rd->msg, HALD_RUN_TIMEOUT, 0, NULL);
-	remove_from_hash_table(rd);
+	remove_run_data (rd);
 	return FALSE;
 }
 
@@ -300,12 +306,16 @@ run_request_run (run_request *r, DBusConnection *con, DBusMessage *msg, GPid *ou
 	else
 		rd->timeout = 0;
 
-	/* Add to the hashtable */
-	list = (GList *)g_hash_table_lookup(udi_hash, r->udi);
-	list = g_list_prepend(list, rd);
+	if (r->is_singleton) {
+		singletons = g_list_prepend(singletons, rd);
+	} else {
+		/* Add to the hashtable */
+		list = (GList *)g_hash_table_lookup(udi_hash, r->udi);
+		list = g_list_prepend(list, rd);
 
-	/* The hash table will take care to not leak the dupped string */
-	g_hash_table_insert(udi_hash, g_strdup(r->udi), list);
+		/* The hash table will take care to not leak the dupped string */
+		g_hash_table_insert(udi_hash, g_strdup(r->udi), list);
+	}
 
 	/* send back PID if requested.. and only emit StartedProcessExited in this case */
 	if (out_pid != NULL) {
@@ -363,6 +373,7 @@ void
 run_kill_all()
 {
 	g_hash_table_foreach_remove(udi_hash, hash_kill_udi, NULL);
+	g_list_foreach(singletons, kill_rd, NULL);
 }
 
 void
diff --git a/hald-runner/runner.h b/hald-runner/runner.h
index 2a18f94..c053381 100644
--- a/hald-runner/runner.h
+++ b/hald-runner/runner.h
@@ -36,6 +36,7 @@ typedef struct {
 	gchar **argv;
 	gchar *input;
 	gboolean error_on_stderr;
+	gboolean is_singleton;
 	guint32 timeout;
 } run_request;
 
diff --git a/hald/hald_runner.c b/hald/hald_runner.c
index 8fd5884..db708e4 100644
--- a/hald/hald_runner.c
+++ b/hald/hald_runner.c
@@ -4,6 +4,7 @@
  * hald_runner.c - Interface to the hal runner helper daemon
  *
  * Copyright (C) 2006 Sjoerd Simons, <sjoerd at luon.net>
+ * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor at codethink.co.uk>
  *
  * Licensed under the Academic Free License version 2.1
  *
@@ -65,6 +66,7 @@ typedef struct {
 	GPid pid;
 	HalDevice *device;
 	HalRunTerminatedCB cb;
+	gboolean is_singleton;
 	gpointer data1;
 	gpointer data2;
 } RunningProcess;
@@ -366,7 +368,8 @@ add_basic_env (DBusMessageIter * iter, const gchar * udi)
 	if (hald_use_syslog) {
 		add_env (iter, "HALD_USE_SYSLOG", "1");
 	}
-	add_env (iter, "UDI", udi);
+	if (udi)
+		add_env (iter, "UDI", udi);
 	add_env (iter, "HALD_DIRECT_ADDR", hald_dbus_local_server_addr ());
 
         /* I'm sure it would be easy to remove use of getenv(3) to add these variables... */
@@ -559,11 +562,9 @@ add_command (DBusMessageIter * iter, const gchar * command_line)
 	return TRUE;
 }
 
-static gboolean
-add_first_part (DBusMessageIter * iter, HalDevice * device,
-		const gchar * command_line, char **extra_env)
+static void
+add_udi (DBusMessageIter * iter, HalDevice * device)
 {
-	DBusMessageIter array_iter;
 	const char *udi;
 
 	if (device != NULL)
@@ -572,7 +573,13 @@ add_first_part (DBusMessageIter * iter, HalDevice * device,
 		udi = "";
 
 	dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &udi);
+}
 
+static gboolean
+add_environment (DBusMessageIter * iter, HalDevice * device,
+		const gchar * command_line, char **extra_env)
+{
+	DBusMessageIter array_iter;
 	dbus_message_iter_open_container (iter,
 					  DBUS_TYPE_ARRAY,
 					  DBUS_TYPE_STRING_AS_STRING,
@@ -580,7 +587,7 @@ add_first_part (DBusMessageIter * iter, HalDevice * device,
 	if (device != NULL)
 		hal_device_property_foreach (device, add_property_to_msg,
 					     &array_iter);
-	add_basic_env (&array_iter, udi);
+	add_basic_env (&array_iter, device ? hal_device_get_udi (device): NULL);
 	add_extra_env (&array_iter, extra_env);
 	dbus_message_iter_close_container (iter, &array_iter);
 
@@ -591,31 +598,37 @@ add_first_part (DBusMessageIter * iter, HalDevice * device,
 }
 
 /* Start a helper, returns true on a successfull start */
-gboolean
-hald_runner_start (HalDevice * device, const gchar * command_line,
-		   char **extra_env, HalRunTerminatedCB cb, gpointer data1,
-		   gpointer data2)
+static gboolean
+runner_start (HalDevice * device, const gchar * command_line,
+	      char **extra_env, gboolean singleton,
+	      HalRunTerminatedCB cb, gpointer data1, gpointer data2)
 {
 	DBusMessage *msg, *reply;
-	DBusError err;
+	DBusError error;
 	DBusMessageIter iter;
 
-	dbus_error_init (&err);
+	dbus_error_init (&error);
 	msg = dbus_message_new_method_call ("org.freedesktop.HalRunner",
 					    "/org/freedesktop/HalRunner",
 					    "org.freedesktop.HalRunner",
-					    "Start");
+					    singleton ? "StartSingleton" : "Start");
 	if (msg == NULL)
 		DIE (("No memory"));
 	dbus_message_iter_init_append (msg, &iter);
 
-	if (!add_first_part (&iter, device, command_line, extra_env))
+	if (!singleton)
+		add_udi (&iter, device);
+
+	if (!add_environment (&iter, device, command_line, extra_env)) {
+		HAL_ERROR (("Error adding environment, device =%p, singleton=%d",
+			device, singleton));
 		goto error;
+	}
 
 	/* Wait for the reply, should be almost instantanious */
 	reply =
 	    dbus_connection_send_with_reply_and_block (runner_connection,
-						       msg, -1, &err);
+						       msg, -1, &error);
 	if (reply) {
 		gboolean ret =
 		    (dbus_message_get_type (reply) ==
@@ -623,7 +636,7 @@ hald_runner_start (HalDevice * device, const gchar * command_line,
 
 		if (ret) {
 			dbus_int64_t pid_from_runner;
-			if (dbus_message_get_args (reply, &err,
+			if (dbus_message_get_args (reply, &error,
 						   DBUS_TYPE_INT64,
 						   &pid_from_runner,
 						   DBUS_TYPE_INVALID)) {
@@ -632,7 +645,11 @@ hald_runner_start (HalDevice * device, const gchar * command_line,
 					rp = g_new0 (RunningProcess, 1);
 					rp->pid = (GPid) pid_from_runner;
 					rp->cb = cb;
-					rp->device = device;
+					rp->is_singleton = singleton;
+					if (singleton)
+						rp->device = NULL;
+					else
+						rp->device = device;
 					rp->data1 = data1;
 					rp->data2 = data2;
 
@@ -649,6 +666,10 @@ hald_runner_start (HalDevice * device, const gchar * command_line,
 		dbus_message_unref (reply);
 		dbus_message_unref (msg);
 		return ret;
+	} else {
+		if (dbus_error_is_set (&error)) {
+			HAL_ERROR (("Error running '%s': %s: %s", command_line, error.name, error.message));
+		}
 	}
 
       error:
@@ -656,6 +677,23 @@ hald_runner_start (HalDevice * device, const gchar * command_line,
 	return FALSE;
 }
 
+gboolean
+hald_runner_start (HalDevice * device, const gchar * command_line,
+		   char **extra_env, HalRunTerminatedCB cb,
+		   gpointer data1, gpointer data2)
+{
+	return runner_start (device, command_line, extra_env, FALSE, cb, data1, data2);
+}
+
+gboolean
+hald_runner_start_singleton (const gchar * command_line,
+			     char **extra_env, HalRunTerminatedCB cb,
+			     gpointer data1, gpointer data2)
+{
+	return runner_start (NULL, command_line, extra_env, TRUE, cb, data1, data2);
+}
+
+
 static void
 process_reply (DBusMessage *m, HelperData *hb)
 {
@@ -759,7 +797,8 @@ hald_runner_run_method (HalDevice * device,
 		DIE (("No memory"));
 	dbus_message_iter_init_append (msg, &iter);
 
-	if (!add_first_part (&iter, device, command_line, extra_env))
+	add_udi (&iter, device);
+	if (!add_environment (&iter, device, command_line, extra_env))
 		goto error;
 
 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &input);
@@ -828,7 +867,8 @@ hald_runner_run_sync (HalDevice * device,
 		DIE (("No memory"));
 	dbus_message_iter_init_append (msg, &iter);
 
-	if (!add_first_part (&iter, device, command_line, extra_env))
+	add_udi (&iter, device);
+	if (!add_environment (&iter, device, command_line, extra_env))
 		goto error;
 
 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &input);
diff --git a/hald/hald_runner.h b/hald/hald_runner.h
index c89eeee..0356132 100644
--- a/hald/hald_runner.h
+++ b/hald/hald_runner.h
@@ -5,6 +5,7 @@
  * hald_runner.h - Interface to the hal runner helper daemon
  *
  * Copyright (C) 2006 Sjoerd Simons <sjoerd at luon.net>
+ * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor at codethink.co.uk>
  *
  * Licensed under the Academic Free License version 2.1
  *
@@ -61,6 +62,11 @@ gboolean
 hald_runner_start (HalDevice *device, const gchar *command_line, char **extra_env, 
 		   HalRunTerminatedCB cb, gpointer data1, gpointer data2);
 
+gboolean
+hald_runner_start_singleton (const gchar * command_line,
+			     char **extra_env, HalRunTerminatedCB cb,
+			     gpointer data1, gpointer data2);
+
 /* Run a helper program using the commandline, with input as infomation on
  * stdin */
 void
-- 
1.5.2-rc3.GIT



--------------010609010103020107060701
Content-Type: text/x-patch;
 name="0002-hald-core-support-for-singleton-addons.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0002-hald-core-support-for-singleton-addons.patch"



More information about the hal mailing list