Improved signal-thread support for the pthread fileserver,
authorNickolai Zeldovich <kolya@mit.edu>
Tue, 14 Jan 2003 01:20:03 +0000 (01:20 +0000)
committerNickolai Zeldovich <kolya@mit.edu>
Tue, 14 Jan 2003 01:20:03 +0000 (01:20 +0000)
which avoids blocking signals in any thread, to appease Linux's
thread signaling semantics.

src/tviced/Makefile.in
src/util/Makefile.in
src/util/softsig.c [new file with mode: 0644]
src/util/softsig.h [new file with mode: 0644]
src/viced/viced.c

index 456e3b2..f643cf7 100644 (file)
@@ -30,7 +30,7 @@ LWPOBJS=lock.o fasttime.o threadname.o
 
 LIBACLOBJS=aclprocs.o netprocs.o
 
-UTILOBJS=assert.o uuid.o serverLog.o fileutil.o netutils.o dirpath.o volparse.o flipbase64.o
+UTILOBJS=assert.o uuid.o serverLog.o fileutil.o netutils.o dirpath.o volparse.o flipbase64.o softsig.o
 
 DIROBJS=buffer.o dir.o salvage.o
 
@@ -85,6 +85,9 @@ netutils.o: ${UTIL}/netutils.c
 dirpath.o: ${UTIL}/dirpath.c
        ${CCRULE}
 
+softsig.o: ${UTIL}/softsig.c
+       ${CCRULE}
+
 lock.o: ${LWP}/lock.c
        ${CCRULE}
 
index b263b52..a61efe4 100644 (file)
@@ -29,6 +29,7 @@ includes = \
        ${TOP_INCDIR}/afs/pthread_glock.h \
        ${TOP_INCDIR}/afs/afs_atomlist.h \
        ${TOP_INCDIR}/afs/afs_lhash.h \
+       ${TOP_INCDIR}/afs/softsig.h \
        ${TOP_INCDIR}/potpourri.h 
 
 all: ${includes} \
@@ -143,6 +144,7 @@ install: \
        ${DESTDIR}${includedir}/afs/pthread_glock.h \
        ${DESTDIR}${includedir}/afs/afs_atomlist.h \
        ${DESTDIR}${includedir}/afs/afs_lhash.h \
+       ${DESTDIR}${includedir}/afs/softsig.h \
        ${DESTDIR}${includedir}/potpourri.h \
        ${DESTDIR}${libdir}/afs/util.a \
        ${DESTDIR}${libdir}/afs/libafsutil.a \
@@ -193,6 +195,9 @@ ${TOP_INCDIR}/afs/afs_atomlist.h: ${srcdir}/afs_atomlist.h
 ${TOP_INCDIR}/afs/afs_lhash.h: ${srcdir}/afs_lhash.h
        ${INSTALL} $? $@
 
+${TOP_INCDIR}/afs/softsig.h: ${srcdir}/softsig.h
+       ${INSTALL} $? $@
+
 ${TOP_INCDIR}/potpourri.h: ${srcdir}/potpourri.h
        ${INSTALL} $? $@
 
@@ -249,6 +254,9 @@ ${DESTDIR}${includedir}/afs/afs_atomlist.h: ${srcdir}/afs_atomlist.h
 ${DESTDIR}${includedir}/afs/afs_lhash.h: ${srcdir}/afs_lhash.h
        ${INSTALL} $? $@
 
+${DESTDIR}${includedir}/afs/softsig.h: ${srcdir}/softsig.h
+       ${INSTALL} $? $@
+
 ${DESTDIR}${includedir}/potpourri.h: ${srcdir}/potpourri.h
        ${INSTALL} $? $@
 
@@ -309,6 +317,9 @@ ${DEST}/include/afs/afs_atomlist.h: ${srcdir}/afs_atomlist.h
 ${DEST}/include/afs/afs_lhash.h: ${srcdir}/afs_lhash.h
        ${INSTALL} $? $@
 
+${DEST}/include/afs/softsig.h: ${srcdir}/softsig.h
+       ${INSTALL} $? $@
+
 ${DEST}/include/potpourri.h: ${srcdir}/potpourri.h
        ${INSTALL} $? $@
 
@@ -352,6 +363,7 @@ dest: \
        ${DEST}/include/afs/pthread_glock.h \
        ${DEST}/include/afs/afs_atomlist.h \
        ${DEST}/include/afs/afs_lhash.h \
+       ${DEST}/include/afs/softsig.h \
        ${DEST}/include/potpourri.h \
        ${DEST}/lib/afs/util.a \
        ${DEST}/lib/afs/libafsutil.a \
diff --git a/src/util/softsig.c b/src/util/softsig.c
new file mode 100644 (file)
index 0000000..886a61f
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#define _POSIX_PTHREAD_SEMANTICS
+#include <assert.h>
+#include <stdio.h>
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static pthread_t softsig_tid;
+static struct {
+  void (*handler) (int);
+  int pending;
+} softsig_sigs[NSIG];
+
+static void *
+softsig_thread (void *arg)
+{
+  sigset_t ss;
+
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR1);
+
+  while (1) {
+    void (*h) (int) = NULL;
+    int i, sigw;
+
+    for (i = 0; i < NSIG; i++)
+      if (softsig_sigs[i].pending) {
+       softsig_sigs[i].pending = 0;
+       h = softsig_sigs[i].handler;
+       break;
+      }
+
+    if (i == NSIG)
+      assert (0 == sigwait (&ss, &sigw));
+    else if (h)
+      h (i);
+  }
+}
+
+void
+softsig_init ()
+{
+  sigset_t ss, os;
+
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR1);
+
+  /* Set mask right away, so we don't accidentally SIGUSR1 the
+   * softsig thread and cause an exit (default action).
+   */
+  assert (0 == pthread_sigmask (SIG_BLOCK, &ss, &os));
+  assert (0 == pthread_create (&softsig_tid, NULL, &softsig_thread, NULL));
+  assert (0 == pthread_sigmask (SIG_SETMASK, &os, NULL));
+}
+
+static void
+softsig_handler (int signo)
+{
+  softsig_sigs[signo].pending = 1;
+  pthread_kill (softsig_tid, SIGUSR1);
+}
+
+void
+softsig_signal (int signo, void (*handler) (int))
+{
+  softsig_sigs[signo].handler = handler;
+  signal (signo, softsig_handler);
+}
+
+#if defined(TEST)
+static void
+print_foo (int signo)
+{
+  printf ("foo, signo = %d, tid = %d\n", signo, pthread_self ());
+}
+
+int
+main ()
+{
+  softsig_init ();
+  softsig_signal (SIGINT, print_foo);
+  printf ("main is tid %d\n", pthread_self ());
+  while (1)
+    sleep (60);
+}
+#endif
diff --git a/src/util/softsig.h b/src/util/softsig.h
new file mode 100644 (file)
index 0000000..53af0d3
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef _SOFTSIG_H
+#define _SOFTSIG_H
+
+void softsig_init ();
+void softsig_signal (int signo, void (*handler) (int));
+
+#endif
index 52b0290..bc2fdb9 100644 (file)
@@ -85,6 +85,9 @@ RCSID("$Header$");
 #endif
 #include "viced.h"
 #include "host.h"
+#ifdef AFS_PTHREAD_ENV
+#include "softsig.h"
+#endif
 #if defined(AFS_SGI_ENV)
 #include "sys/schedctl.h"
 #include "sys/lock.h"
@@ -235,22 +238,32 @@ int fs_rxstat_userok(struct rx_call *call)
 
 static void ResetCheckSignal(void)
 {
-#ifdef AFS_HPUX_ENV
-    signal(SIGPOLL, CheckSignal_Signal);
-#else
-#ifdef AFS_NT40_ENV
-    signal(SIGUSR2, CheckSignal_Signal);
+    int signo;
+
+#if defined(AFS_HPUX_ENV)
+    signo = SIGPOLL;
+#elsif defined(AFS_NT40_ENV)
+    signo = SIGUSR2;
 #else
-    signal(SIGXCPU, CheckSignal_Signal);
+    signo = SIGXCPU;
 #endif
+
+#if defined(AFS_PTHREAD_ENV)
+    softsig_signal(signo, CheckSignal_Signal);
+#else
+    signal(signo, CheckSignal_Signal);
 #endif
 }
 
 static void ResetCheckDescriptors(void)
 {
 #ifndef AFS_NT40_ENV
+#if defined(AFS_PTHREAD_ENV)
+    softsig_signal(SIGTERM, CheckDescriptors_Signal);
+#else
     signal(SIGTERM, CheckDescriptors_Signal);
 #endif
+#endif
 }
 
 
@@ -319,21 +332,6 @@ CheckAdminName()
 } /*CheckAdminName*/
 
 
-#ifdef AFS_PTHREAD_ENV
-/* A special LWP that will receive signals, to avoid deadlock */
-static void SignalLWP()
-{
-    sigset_t nsigset;
-
-    sigfillset(&nsigset);
-    assert(AFS_SET_SIGMASK(SIG_UNBLOCK, &nsigset, NULL) == 0);
-
-    while (1)
-       sleep(60);
-}
-#endif
-
-
 /* This LWP does things roughly every 5 minutes */
 static void FiveMinuteCheckLWP()
 {
@@ -1353,7 +1351,6 @@ main(int argc, char * argv[])
 #ifdef AFS_PTHREAD_ENV
     pthread_t parentPid, serverPid;
     pthread_attr_t tattr;
-    sigset_t nsigset;
 #else /* AFS_PTHREAD_ENV */
     PROCESS parentPid, serverPid;
 #endif /* AFS_PTHREAD_ENV */
@@ -1426,6 +1423,11 @@ main(int argc, char * argv[])
     ViceLog(0, ("File server starting\n"));
 #endif
 
+#if defined(AFS_PTHREAD_ENV)
+    /* initialize the pthread soft signal handler thread */
+    softsig_init();
+#endif
+
     /* install signal handlers for controlling the fileserver process */
     ResetCheckSignal();  /* set CheckSignal_Signal() sig handler */
     ResetCheckDescriptors();  /* set CheckDescriptors_Signal() sig handler */
@@ -1625,10 +1627,6 @@ main(int argc, char * argv[])
 #ifdef AFS_PTHREAD_ENV
     assert(pthread_attr_init(&tattr) == 0);
     assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
-    /* Block signals in this thread (and children), create a signal thread */
-    sigfillset(&nsigset);
-    assert(AFS_SET_SIGMASK(SIG_BLOCK, &nsigset, NULL) == 0);
-    assert(pthread_create(&serverPid, &tattr, (void *)SignalLWP, NULL) == 0);
 
     assert(pthread_create(&serverPid, &tattr, (void *)FiveMinuteCheckLWP, &fiveminutes) == 0);
     assert(pthread_create(&serverPid, &tattr, (void *)HostCheckLWP, &fiveminutes) == 0);
@@ -1676,8 +1674,14 @@ main(int argc, char * argv[])
                   FS_HostName, hoststr, FS_HostAddr_NBO, FS_HostAddr_HBO));
     }
 
-    /* Install handler to catch the shutdown signal */
-    signal(SIGQUIT, ShutDown_Signal); /* bosserver assumes SIGQUIT shutdown */
+    /* Install handler to catch the shutdown signal;
+     * bosserver assumes SIGQUIT shutdown
+     */
+#if defined(AFS_PTHREAD_ENV)
+    softsig_signal(SIGQUIT, ShutDown_Signal);
+#else
+    signal(SIGQUIT, ShutDown_Signal);
+#endif
 
     ViceLog(0,("File Server started %s",
               afs_ctime(&tp.tv_sec, tbuffer, sizeof(tbuffer))));