/src/samba/lib/util/signal.c
Line | Count | Source |
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 3 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, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "replace.h" |
22 | | #include "system/wait.h" |
23 | | #include "debug.h" |
24 | | #include "lib/util/signal.h" /* Avoid /usr/include/signal.h */ |
25 | | |
26 | | /** |
27 | | * @file |
28 | | * @brief Signal handling |
29 | | */ |
30 | | |
31 | | /**************************************************************************** |
32 | | Catch child exits and reap the child zombie status. |
33 | | ****************************************************************************/ |
34 | | |
35 | | static void sig_cld(int signum) |
36 | 0 | { |
37 | 0 | while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) |
38 | 0 | ; |
39 | | |
40 | | /* |
41 | | * Turns out it's *really* important not to |
42 | | * restore the signal handler here if we have real POSIX |
43 | | * signal handling. If we do, then we get the signal re-delivered |
44 | | * immediately - hey presto - instant loop ! JRA. |
45 | | */ |
46 | |
|
47 | | #if !defined(HAVE_SIGACTION) |
48 | | CatchSignal(SIGCLD, sig_cld); |
49 | | #endif |
50 | 0 | } |
51 | | |
52 | | /**************************************************************************** |
53 | | catch child exits - leave status; |
54 | | ****************************************************************************/ |
55 | | |
56 | | static void sig_cld_leave_status(int signum) |
57 | 0 | { |
58 | | /* |
59 | | * Turns out it's *really* important not to |
60 | | * restore the signal handler here if we have real POSIX |
61 | | * signal handling. If we do, then we get the signal re-delivered |
62 | | * immediately - hey presto - instant loop ! JRA. |
63 | | */ |
64 | |
|
65 | | #if !defined(HAVE_SIGACTION) |
66 | | CatchSignal(SIGCLD, sig_cld_leave_status); |
67 | | #endif |
68 | 0 | } |
69 | | |
70 | | /** |
71 | | Block sigs. |
72 | | **/ |
73 | | |
74 | | void BlockSignals(bool block, int signum) |
75 | 0 | { |
76 | 0 | #ifdef HAVE_SIGPROCMASK |
77 | 0 | sigset_t set; |
78 | 0 | sigemptyset(&set); |
79 | 0 | sigaddset(&set,signum); |
80 | 0 | sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL); |
81 | | #elif defined(HAVE_SIGBLOCK) |
82 | | if (block) { |
83 | | sigblock(sigmask(signum)); |
84 | | } else { |
85 | | sigsetmask(siggetmask() & ~sigmask(signum)); |
86 | | } |
87 | | #else |
88 | | /* yikes! This platform can't block signals? */ |
89 | | static int done; |
90 | | if (!done) { |
91 | | DEBUG(0,("WARNING: No signal blocking available\n")); |
92 | | done=1; |
93 | | } |
94 | | #endif |
95 | 0 | } |
96 | | |
97 | | /** |
98 | | Catch a signal. This should implement the following semantics: |
99 | | |
100 | | 1) The handler remains installed after being called. |
101 | | 2) The signal should be blocked during handler execution. |
102 | | **/ |
103 | | |
104 | | void (*CatchSignal(int signum,void (*handler)(int )))(int) |
105 | 0 | { |
106 | 0 | #ifdef HAVE_SIGACTION |
107 | 0 | struct sigaction act; |
108 | 0 | struct sigaction oldact; |
109 | |
|
110 | 0 | ZERO_STRUCT(act); |
111 | |
|
112 | 0 | act.sa_handler = handler; |
113 | 0 | #ifdef SA_RESTART |
114 | | /* |
115 | | * We *want* SIGALRM to interrupt a system call. |
116 | | */ |
117 | 0 | if(signum != SIGALRM) |
118 | 0 | act.sa_flags = SA_RESTART; |
119 | 0 | #endif |
120 | 0 | sigemptyset(&act.sa_mask); |
121 | 0 | sigaddset(&act.sa_mask,signum); |
122 | 0 | sigaction(signum,&act,&oldact); |
123 | 0 | return oldact.sa_handler; |
124 | | #else /* !HAVE_SIGACTION */ |
125 | | /* FIXME: need to handle sigvec and systems with broken signal() */ |
126 | | return signal(signum, handler); |
127 | | #endif |
128 | 0 | } |
129 | | |
130 | | /** |
131 | | Ignore SIGCLD via whatever means is necessary for this OS. |
132 | | **/ |
133 | | |
134 | | void (*CatchChild(void))(int) |
135 | 0 | { |
136 | 0 | return CatchSignal(SIGCLD, sig_cld); |
137 | 0 | } |
138 | | |
139 | | /** |
140 | | Catch SIGCLD but leave the child around so it's status can be reaped. |
141 | | **/ |
142 | | |
143 | | void (*CatchChildLeaveStatus(void))(int) |
144 | 0 | { |
145 | | return CatchSignal(SIGCLD, sig_cld_leave_status); |
146 | 0 | } |