r9791: r11611@blu: tridge | 2005-08-30 21:48:22 +1000
[ira/wip.git] / source4 / lib / signal.c
1 /* 
2    Unix SMB/CIFS implementation.
3    signal handling functions
4
5    Copyright (C) Andrew Tridgell 1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "system/wait.h"
24
25 /****************************************************************************
26  Catch child exits and reap the child zombie status.
27 ****************************************************************************/
28
29 static void sig_cld(int signum)
30 {
31         while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0)
32                 ;
33
34         /*
35          * Turns out it's *really* important not to
36          * restore the signal handler here if we have real POSIX
37          * signal handling. If we do, then we get the signal re-delivered
38          * immediately - hey presto - instant loop ! JRA.
39          */
40
41 #if !defined(HAVE_SIGACTION)
42         CatchSignal(SIGCLD, sig_cld);
43 #endif
44 }
45
46 /****************************************************************************
47 catch child exits - leave status;
48 ****************************************************************************/
49
50 static void sig_cld_leave_status(int signum)
51 {
52         /*
53          * Turns out it's *really* important not to
54          * restore the signal handler here if we have real POSIX
55          * signal handling. If we do, then we get the signal re-delivered
56          * immediately - hey presto - instant loop ! JRA.
57          */
58
59 #if !defined(HAVE_SIGACTION)
60         CatchSignal(SIGCLD, sig_cld_leave_status);
61 #endif
62 }
63
64 /*******************************************************************
65  Block sigs.
66 ********************************************************************/
67
68 void BlockSignals(BOOL block,int signum)
69 {
70 #ifdef HAVE_SIGPROCMASK
71         sigset_t set;
72         sigemptyset(&set);
73         sigaddset(&set,signum);
74         sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
75 #elif defined(HAVE_SIGBLOCK)
76         if (block) {
77                 sigblock(sigmask(signum));
78         } else {
79                 sigsetmask(siggetmask() & ~sigmask(signum));
80         }
81 #else
82         /* yikes! This platform can't block signals? */
83         static int done;
84         if (!done) {
85                 DEBUG(0,("WARNING: No signal blocking available\n"));
86                 done=1;
87         }
88 #endif
89 }
90
91 /*******************************************************************
92  Catch a signal. This should implement the following semantics:
93
94  1) The handler remains installed after being called.
95  2) The signal should be blocked during handler execution.
96 ********************************************************************/
97
98 void (*CatchSignal(int signum,void (*handler)(int )))(int)
99 {
100 #ifdef HAVE_SIGACTION
101         struct sigaction act;
102         struct sigaction oldact;
103
104         ZERO_STRUCT(act);
105
106         act.sa_handler = handler;
107 #ifdef SA_RESTART
108         /*
109          * We *want* SIGALRM to interrupt a system call.
110          */
111         if(signum != SIGALRM)
112                 act.sa_flags = SA_RESTART;
113 #endif
114         sigemptyset(&act.sa_mask);
115         sigaddset(&act.sa_mask,signum);
116         sigaction(signum,&act,&oldact);
117         return oldact.sa_handler;
118 #else /* !HAVE_SIGACTION */
119         /* FIXME: need to handle sigvec and systems with broken signal() */
120         return signal(signum, handler);
121 #endif
122 }
123
124 /*******************************************************************
125  Ignore SIGCLD via whatever means is necessary for this OS.
126 ********************************************************************/
127
128 void CatchChild(void)
129 {
130         CatchSignal(SIGCLD, sig_cld);
131 }
132
133 /*******************************************************************
134  Catch SIGCLD but leave the child around so it's status can be reaped.
135 ********************************************************************/
136
137 void CatchChildLeaveStatus(void)
138 {
139         CatchSignal(SIGCLD, sig_cld_leave_status);
140 }