hal/hald Makefile.am, 1.22, 1.23 callout.c, 1.11, 1.12 logger.h, 1.5,
1.6
David Zeuthen
david at pdx.freedesktop.org
Sat May 1 12:29:19 PDT 2004
Update of /cvs/hal/hal/hald
In directory pdx:/tmp/cvs-serv19656/hald
Modified Files:
Makefile.am callout.c logger.h
Log Message:
2004-05-01 David Zeuthen <david at fubar.dk>
* hald/Makefile.am (install-data-local): create /etc/hal/property.d
* tools/callouts/fstab-update.sh: s/msdos/vfat/ if applicable
* hald/logger.h: include stdio.h, stdlib.h since DIE macro uses this
* doc/TODO: removed a TODO-note :-)
* hald/callout.c (wait_for_callout): removed
(handle_sigchld): new function
(iochn_data): new function
(process_callouts): install signal handler and setup GIOChannel
stuff; don't install timeout for waiting for child
* hald/linux/class_device.c (class_device_detection_done): removed
* hald/linux/bus_device.c (bus_device_detection_done): removed
Index: Makefile.am
===================================================================
RCS file: /cvs/hal/hal/hald/Makefile.am,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- a/Makefile.am 30 Apr 2004 17:01:23 -0000 1.22
+++ b/Makefile.am 1 May 2004 19:29:17 -0000 1.23
@@ -102,4 +102,5 @@
install-data-local :
$(mkinstalldirs) $(DESTDIR)$(SYSCONFDIR)/hal/device.d
$(mkinstalldirs) $(DESTDIR)$(SYSCONFDIR)/hal/capability.d
+ $(mkinstalldirs) $(DESTDIR)$(SYSCONFDIR)/hal/property.d
Index: callout.c
===================================================================
RCS file: /cvs/hal/hal/hald/callout.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- a/callout.c 26 Apr 2004 20:42:13 -0000 1.11
+++ b/callout.c 1 May 2004 19:29:17 -0000 1.12
@@ -31,6 +31,7 @@
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#include "callout.h"
#include "logger.h"
@@ -58,8 +59,14 @@
static void process_callouts (void);
-/* Key: HalDevice Value: pointer to GSList of Callouts */
+/* Callouts that still needing to be processed
+ *
+ * Key: HalDevice Value: pointer to GSList of Callouts */
static GHashTable *pending_callouts = NULL;
+
+/* List of Callouts currently being processed */
+static GSList *active_callouts = NULL;
+
static gboolean processing_callouts = FALSE;
static void
@@ -152,37 +159,91 @@
return TRUE;
}
+static gboolean have_installed_sigchild_handler = FALSE;
+static int unix_signal_pipe_fds[2];
+static GIOChannel *iochn;
+
+static void
+handle_sigchld (int value)
+{
+ static char marker[1] = {'D'};
+
+ /* write a 'D' character to the other end to tell that a child has
+ * terminated. Note that 'the other end' is a GIOChannel thingy
+ * that is only called from the mainloop - thus this is how we
+ * defer this since UNIX signal handlers are evil
+ *
+ * Oh, and write(2) is indeed reentrant */
+ write (unix_signal_pipe_fds[1], marker, 1);
+}
+
static gboolean
-wait_for_callout (gpointer user_data)
+iochn_data (GIOChannel *source, GIOCondition condition, gpointer user_data)
{
- Callout *callout = user_data;
- int status;
+ gsize bytes_read;
+ gchar data[1];
+ GError *err = NULL;
+ pid_t child_pid;
+ Callout *callout;
+ GSList *it;
- status = waitpid (callout->pid, NULL, WNOHANG);
- if (status == 0) {
- /* Not finished yet... */
- return TRUE;
- } else if (status == -1) {
- if (errno == EINTR)
- return TRUE;
- else {
- HAL_WARNING (("waitpid errno %d: %s", errno,
- strerror (errno)));
+ /* Empty the pipe; one character per dead child */
+ if (G_IO_STATUS_NORMAL !=
+ g_io_channel_read_chars (source, data, 1, &bytes_read, &err)) {
+ HAL_ERROR (("Error emptying callout notify pipe: %s",
+ err->message));
+ g_error_free (err);
+ goto out;
+ }
+
+ /* signals are not queued, so loop until no zombies are left */
+ while (TRUE) {
+ /* wait for any child - this is sane because the reason we got
+ * invoked is the fact that a child has exited */
+ child_pid = waitpid (-1, NULL, WNOHANG);
+
+ if (child_pid == 0) {
+ /* no more childs */
+ goto out;
+ } else if (child_pid == -1) {
+ /* this can happen indeed since we loop */
+ goto out;
}
- } else {
+
+ /* Now find the corresponding Callout object */
+ callout = NULL;
+ for (it=g_slist_nth(active_callouts, 0);
+ it != NULL;
+ it = g_slist_next(it)) {
+ Callout *callout_it = (Callout *) it->data;
+ if (callout_it->pid == child_pid) {
+ callout = callout_it;
+ break;
+ }
+ }
+
+ if (callout == NULL) {
+ /* this should never happen */
+ HAL_ERROR (("Cannot find callout for terminated "
+ "child with pid %d", child_pid));
+ goto out;
+ }
+
+
if (callout->last_of_device)
hal_device_callouts_finished (callout->device);
-
+
g_free (callout->filename);
g_strfreev (callout->envp);
g_object_unref (callout->device);
g_free (callout);
-
+
process_callouts ();
}
-
- return FALSE;
+
+out:
+ return TRUE;
}
static void
@@ -194,6 +255,28 @@
GError *err = NULL;
int num_props;
+ if (!have_installed_sigchild_handler) {
+ guint iochn_listener_source_id;
+
+ /* create pipe */
+ if (pipe (unix_signal_pipe_fds) != 0) {
+ DIE (("Could not setup pipe, errno=%d", errno));
+ }
+
+ /* setup glib handler - 0 is for reading, 1 is for writing */
+ iochn = g_io_channel_unix_new (unix_signal_pipe_fds[0]);
+ if (iochn == NULL)
+ DIE (("Could not create GIOChannel"));
+
+ /* get callback when there is data to read */
+ iochn_listener_source_id = g_io_add_watch (
+ iochn, G_IO_IN, iochn_data, NULL);
+
+ /* setup unix signal handler */
+ signal(SIGCHLD, handle_sigchld);
+ have_installed_sigchild_handler = TRUE;
+ }
+
if (pending_callouts == NULL ||
g_hash_table_size (pending_callouts) == 0) {
processing_callouts = FALSE;
@@ -239,6 +322,8 @@
*/
callout->envp[callout->envp_index] = NULL;
+ active_callouts = g_slist_append (active_callouts, callout);
+
if (!g_spawn_async (callout->working_dir, argv, callout->envp,
G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
&callout->pid, &err)) {
@@ -246,8 +331,6 @@
err->message));
g_error_free (err);
}
-
- g_timeout_add (250, wait_for_callout, callout);
}
static gboolean
Index: logger.h
===================================================================
RCS file: /cvs/hal/hal/hald/logger.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- a/logger.h 3 Mar 2004 17:56:56 -0000 1.5
+++ b/logger.h 1 May 2004 19:29:17 -0000 1.6
@@ -26,6 +26,9 @@
#ifndef LOGGER_H
#define LOGGER_H
+#include <stdio.h>
+#include <stdlib.h>
+
/**
* @addtogroup HalDaemonLogging
*
More information about the hal-commit
mailing list