dovecot-1.2: Added API for waiting child processes.

dovecot at dovecot.org dovecot at dovecot.org
Wed Oct 22 00:29:58 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/3e8f847f68a4
changeset: 8306:3e8f847f68a4
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Oct 22 00:28:46 2008 +0300
description:
Added API for waiting child processes.

diffstat:

3 files changed, 146 insertions(+)
src/lib/Makefile.am  |    2 
src/lib/child-wait.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/lib/child-wait.h |   36 ++++++++++++++++

diffs (171 lines):

diff -r e4d0ce4d3420 -r 3e8f847f68a4 src/lib/Makefile.am
--- a/src/lib/Makefile.am	Mon Oct 20 20:00:19 2008 +0300
+++ b/src/lib/Makefile.am	Wed Oct 22 00:28:46 2008 +0300
@@ -15,6 +15,7 @@ liblib_a_SOURCES = \
 	base64.c \
 	bsearch-insert-pos.c \
 	buffer.c \
+	child-wait.c \
 	close-keep-errno.c \
 	compat.c \
 	crc32.c \
@@ -115,6 +116,7 @@ headers = \
 	base64.h \
 	bsearch-insert-pos.h \
 	buffer.h \
+	child-wait.h \
 	close-keep-errno.h \
 	compat.h \
 	crc32.h \
diff -r e4d0ce4d3420 -r 3e8f847f68a4 src/lib/child-wait.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/child-wait.c	Wed Oct 22 00:28:46 2008 +0300
@@ -0,0 +1,108 @@
+/* Copyright (c) 2007-2008 Icecap authors, see the included COPYING file */
+
+#include "lib.h"
+#include "lib-signals.h"
+#include "hash.h"
+#include "child-wait.h"
+
+#include <sys/wait.h>
+
+struct child_wait {
+	unsigned int pid_count;
+
+	child_wait_callback_t *callback;
+	void *context;
+};
+
+struct hash_table *child_pids;
+
+#undef child_wait_new_with_pid
+struct child_wait *
+child_wait_new_with_pid(pid_t pid, child_wait_callback_t *callback,
+			void *context)
+{
+	struct child_wait *wait;
+
+	wait = i_new(struct child_wait, 1);
+	wait->callback = callback;
+	wait->context = context;
+
+	if (pid != (pid_t)-1)
+		child_wait_add_pid(wait, pid);
+	return wait;
+}
+
+void child_wait_free(struct child_wait **_wait)
+{
+	struct child_wait *wait = *_wait;
+	struct hash_iterate_context *iter;
+	void *key, *value;
+
+	*_wait = NULL;
+
+	if (wait->pid_count > 0) {
+		/* this should be rare, so iterating hash is fast enough */
+		iter = hash_iterate_init(child_pids);
+		while (hash_iterate(iter, &key, &value)) {
+			if (value == wait) {
+				hash_remove(child_pids, key);
+				if (--wait->pid_count == 0)
+					break;
+			}
+		}
+		hash_iterate_deinit(&iter);
+	}
+
+	i_free(wait);
+}
+
+void child_wait_add_pid(struct child_wait *wait, pid_t pid)
+{
+	wait->pid_count++;
+	hash_insert(child_pids, POINTER_CAST(pid), wait);
+}
+
+void child_wait_remove_pid(struct child_wait *wait, pid_t pid)
+{
+	wait->pid_count--;
+	hash_remove(child_pids, POINTER_CAST(pid));
+}
+
+static void
+sigchld_handler(int signo ATTR_UNUSED, void *context ATTR_UNUSED)
+{
+	struct child_wait_status status;
+
+	while ((status.pid = waitpid(-1, &status.status, WNOHANG)) > 0) {
+		status.wait = hash_lookup(child_pids, POINTER_CAST(status.pid));
+		if (status.wait != NULL) {
+			child_wait_remove_pid(status.wait, status.pid);
+			status.wait->callback(&status, status.wait->context);
+		}
+	}
+
+	if (status.pid == -1 && errno != EINTR && errno != ECHILD)
+		i_error("waitpid() failed: %m");
+}
+
+void child_wait_init(void)
+{
+	child_pids = hash_create(default_pool, default_pool, 0, NULL, NULL);
+
+	lib_signals_set_handler(SIGCHLD, TRUE, sigchld_handler, NULL);
+}
+
+void child_wait_deinit(void)
+{
+	struct hash_iterate_context *iter;
+	void *key, *value;
+
+	lib_signals_unset_handler(SIGCHLD, sigchld_handler, NULL);
+
+	iter = hash_iterate_init(child_pids);
+	while (hash_iterate(iter, &key, &value))
+		i_free(value);
+	hash_iterate_deinit(&iter);
+
+	hash_destroy(&child_pids);
+}
diff -r e4d0ce4d3420 -r 3e8f847f68a4 src/lib/child-wait.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/child-wait.h	Wed Oct 22 00:28:46 2008 +0300
@@ -0,0 +1,36 @@
+#ifndef CHILD_WAIT_H
+#define CHILD_WAIT_H
+
+struct child_wait_status {
+	struct child_wait *wait;
+
+	pid_t pid;
+	int status;
+};
+
+typedef void child_wait_callback_t(const struct child_wait_status *status,
+				   void *context);
+
+struct child_wait *
+child_wait_new_with_pid(pid_t pid, child_wait_callback_t *callback,
+			void *context);
+#ifdef CONTEXT_TYPE_SAFETY
+#  define child_wait_new_with_pid(pid, callback, context) \
+	({(void)(1 ? 0 : callback((const struct child_wait_status *)0, \
+				  context)); \
+	  child_wait_new_with_pid(pid, (child_wait_callback_t *)callback, context); })
+#else
+#  define child_wait_new_with_pid(pid, callback, context) \
+	  child_wait_new_with_pid(pid, (child_wait_callback_t *)callback, context)
+#endif
+#define child_wait_new(callback, context) \
+	child_wait_new_with_pid((pid_t)-1, callback, context)
+void child_wait_free(struct child_wait **wait);
+
+void child_wait_add_pid(struct child_wait *wait, pid_t pid);
+void child_wait_remove_pid(struct child_wait *wait, pid_t pid);
+
+void child_wait_init(void);
+void child_wait_deinit(void);
+
+#endif


More information about the dovecot-cvs mailing list