summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>2001-02-21 01:15:48 +0000
committerrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>2001-02-21 01:15:48 +0000
commitead13b04cfb76d2cdcd1588098e31c913d1fc05f (patch)
tree712139216fe4362bc01c14bf6d0ffb2294b588e5
parentbb56b8f91ffb550b2459c092b1961e159ddf416a (diff)
downloadlibapr-ead13b04cfb76d2cdcd1588098e31c913d1fc05f.tar.gz
Add some functions to APR's thread/processes support to allow a single
thread to handle all signal processing. git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@61266 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--build/apr_threads.m424
-rw-r--r--include/apr_thread_proc.h22
-rw-r--r--threadproc/unix/signals.c47
3 files changed, 93 insertions, 0 deletions
diff --git a/build/apr_threads.m4 b/build/apr_threads.m4
index 9a9e2a013..05602eea6 100644
--- a/build/apr_threads.m4
+++ b/build/apr_threads.m4
@@ -156,3 +156,27 @@ else
fi
])dnl
+AC_DEFUN(APACHE_CHECK_SIGWAIT_ONE_ARG,[
+ AC_CACHE_CHECK(whether sigwait takes one argument,ac_cv_sigwait_one_arg,[
+ AC_TRY_COMPILE([
+#ifdef __NETBSD__
+ /* When using the unproven-pthreads package, we need to pull in this
+ * header to get a prototype for sigwait(). Else things will fail later
+ * on. XXX Should probably be fixed in the unproven-pthreads package.
+ */
+#include <pthread.h>
+#endif
+#include <signal.h>
+],[
+ sigset_t set;
+
+ sigwait(&set);
+],[
+ ac_cv_sigwait_one_arg=yes
+],[
+ ac_cv_sigwait_one_arg=no
+])])
+ if test "$ac_cv_sigwait_one_arg" = "yes"; then
+ AC_DEFINE(SIGWAIT_TAKES_ONE_ARG,1,[ ])
+ fi
+])
diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h
index a9d6fde34..0b9694985 100644
--- a/include/apr_thread_proc.h
+++ b/include/apr_thread_proc.h
@@ -584,6 +584,28 @@ APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int sig);
APR_DECLARE(void) apr_pool_note_subprocess(apr_pool_t *a, apr_proc_t *pid,
enum kill_conditions how);
+/**
+ * Setup the process for a single thread to be used for all signal handling.
+ * @warn This must be called before any threads are created
+ * @deffunc apr_status_t apr_setup_signal_thread(void)
+ */
+APR_DECLARE(apr_status_t) apr_setup_signal_thread(void);
+
+/**
+ * Create a thread that will listen for signals. The thread will loop
+ * forever, calling a provided function whenever it receives a signal. That
+ * functions should return 1 if the signal has been handled, 0 otherwise.
+ * @param td The newly created thread
+ * @param tattr The threadattr to use when creating the thread
+ * @param signal_handler The function to call when a signal is received
+ * @param p The pool to use when creating the thread
+ * @deffunc apr_status_t apr_create_signal_thread(apr_thread_t **td, apr_threadattr_t *tattr, int (*signal_handler)(int signum), apr_pool_t *p)
+ */
+APR_DECLARE(apr_status_t) apr_create_signal_thread(apr_thread_t **td,
+ apr_threadattr_t *tattr,
+ int (*signal_handler)(int signum),
+ apr_pool_t *p);
+
#ifdef __cplusplus
}
#endif
diff --git a/threadproc/unix/signals.c b/threadproc/unix/signals.c
index 6e5f51159..ee9d9f2b6 100644
--- a/threadproc/unix/signals.c
+++ b/threadproc/unix/signals.c
@@ -63,6 +63,7 @@
#include "apr_want.h"
#include <assert.h>
+#include <pthread.h>
apr_status_t apr_proc_kill(apr_proc_t *proc, int signum)
@@ -264,3 +265,49 @@ const char *apr_signal_get_description(int signum)
}
#endif /* SYS_SIGLIST_DECLARED */
+
+static void *signal_thread_func(void *signal_handler)
+{
+ sigset_t sig_mask;
+ int (*sig_func)(int signum) = signal_handler;
+
+ /* This thread will be the one responsible for handling signals */
+ sigfillset(&sig_mask);
+ while (1) {
+ int signal_received;
+
+ apr_sigwait(&sig_mask, &signal_received);
+ if (sig_func(signal_received) == 1) {
+ return NULL;
+ }
+ }
+}
+
+APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
+{
+ sigset_t sig_mask;
+ int rv;
+
+ /* All threads should mask signals out, accoring to sigwait(2) man page */
+ sigfillset(&sig_mask);
+
+#ifdef SIGPROCMASK_SETS_THREAD_MASK
+ rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL);
+#else
+ if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
+#ifdef PTHREAD_SETS_ERRNO
+ rv = errno;
+#endif
+ }
+#endif
+ return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_create_signal_thread(apr_thread_t **td,
+ apr_threadattr_t *tattr,
+ int (*signal_handler)(int signum),
+ apr_pool_t *p)
+{
+ return apr_thread_create(td, tattr, signal_thread_func, signal_handler, p);
+}
+