softsig-update-20030602
[openafs.git] / src / util / softsig.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #define _POSIX_PTHREAD_SEMANTICS
11 #include <afs/param.h>
12 #include <assert.h>
13 #include <stdio.h>
14 #ifndef  AFS_NT40_ENV
15 #include <signal.h>
16 #include <unistd.h>
17 #else
18 #include <afs/procmgmt.h>
19 #endif
20 #include <pthread.h>
21
22 #include "pthread_nosigs.h"
23
24 static pthread_t softsig_tid;
25 static struct {
26   void (*handler) (int);
27   int pending;
28   int fatal;
29   int inited;
30 } softsig_sigs[NSIG];
31
32 static void *
33 softsig_thread (void *arg)
34 {
35   sigset_t ss,os;
36   int i;
37
38   sigemptyset (&ss);
39   /* get the list of signals _not_ blocked by AFS_SIGSET_CLEAR() */
40   pthread_sigmask (SIG_BLOCK, &ss, &os);
41   pthread_sigmask (SIG_SETMASK, &os, NULL);
42   sigaddset (&ss, SIGUSR1);
43   for (i = 0; i < NSIG; i++) {
44     if (!sigismember(&os, i) && i != SIGSTOP && i != SIGKILL) {
45       sigaddset(&ss, i);
46       softsig_sigs[i].fatal = 1;
47     }
48   }
49   
50   while (1) {
51     void (*h) (int);
52     int sigw;
53
54     h = NULL;
55
56     for (i = 0; i < NSIG; i++) {
57       if (softsig_sigs[i].handler && !softsig_sigs[i].inited) {
58         sigaddset(&ss, i);
59         softsig_sigs[i].inited = 1;
60       }
61       if (softsig_sigs[i].pending) {
62         softsig_sigs[i].pending = 0;
63         h = softsig_sigs[i].handler;
64         break;
65       }
66     }
67     if (i == NSIG) {
68       sigwait (&ss, &sigw);
69       if (sigw != SIGUSR1) {
70         if (softsig_sigs[sigw].fatal)
71           exit(0);
72         softsig_sigs[sigw].pending=1;
73       }
74     } else if (h)
75       h (i);
76   }
77 }
78
79 void
80 softsig_init ()
81 {
82   int rc;
83   AFS_SIGSET_DECL;
84   AFS_SIGSET_CLEAR();
85   rc = pthread_create (&softsig_tid, NULL, &softsig_thread, NULL);
86   assert(0 == rc);
87   AFS_SIGSET_RESTORE();
88 }
89
90 static void
91 softsig_handler (int signo)
92 {
93   signal (signo, softsig_handler);
94   softsig_sigs[signo].pending = 1;
95   pthread_kill (softsig_tid, SIGUSR1);
96 }
97
98 void
99 softsig_signal (int signo, void (*handler) (int))
100 {
101   softsig_sigs[signo].handler = handler;
102   softsig_sigs[signo].inited = 0;
103   signal (signo, softsig_handler);
104   pthread_kill (softsig_tid, SIGUSR1);
105 }
106
107 #if defined(TEST)
108 static void
109 print_foo (int signo)
110 {
111   printf ("foo, signo = %d, tid = %d\n", signo, pthread_self ());
112 }
113
114 int
115 main ()
116 {
117   softsig_init ();
118   softsig_signal (SIGINT, print_foo);
119   printf ("main is tid %d\n", pthread_self ());
120   while (1)
121     sleep (60);
122 }
123 #endif