Convert over to use GetOpt::Long and introduce -f and -h.
[fvwm.git] / libs / fvwmsignal.c
blob3d373c3127fcf5963b047b071029c9ddb478ba0a
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * fvwmsignal.c
18 * Written by Chris Rankin, rankinc@zipworld.com.au
22 #include "config.h"
24 #include <sys/wait.h>
25 #include <setjmp.h>
26 #include <errno.h>
27 #include "fvwmsignal.h"
29 #define true 1
30 #define false 0
33 typedef enum { SIG_INIT=0, SIG_DONE } SIG_STATUS;
35 volatile sig_atomic_t isTerminated = false;
37 static volatile sig_atomic_t canJump = false;
38 #ifdef HAVE_SIGSETJMP
39 static sigjmp_buf deadJump;
40 #define SIGSETJMP(env, savesigs) sigsetjmp(env, savesigs)
41 #else
42 static jmp_buf deadJump;
43 #define SIGSETJMP(env, savesigs) setjmp(env)
44 #endif
45 #if defined(HAVE_SIGLONGJMP) && defined(HAVE_SIGSETJMP)
46 #define SIGLONGJMP(env, val) siglongjmp(env, val)
47 #else
48 #define SIGLONGJMP(env, val) longjmp(env, val)
49 #endif
51 * Reap child processes, preventing them from becoming zombies.
52 * We do this asynchronously within the SIGCHLD handler so that
53 * "it just happens".
55 RETSIGTYPE
56 fvwmReapChildren(int sig)
58 (void)sig;
60 BSD_BLOCK_SIGNALS;
62 * This is a signal handler, AND SO MUST BE REENTRANT!
63 * Now the wait() functions are safe here, but please don't
64 * add anything unless you're SURE that the new functions
65 * (plus EVERYTHING they call) are also reentrant. There
66 * are very few functions which are truly safe.
68 #if HAVE_WAITPID
69 while (waitpid(-1, NULL, WNOHANG) > 0)
71 /* nothing to do here */
73 #elif HAVE_WAIT3
74 while (wait3(NULL, WNOHANG, NULL) > 0)
76 /* nothing to do here */
78 #else
79 # error One of waitpid or wait3 is needed.
80 #endif
81 BSD_UNBLOCK_SIGNALS;
83 SIGNAL_RETURN;
86 #ifdef USE_BSD_SIGNALS
87 static int term_sigs;
90 * fvwmSetSignalMask - store the set of mutually exclusive signals
91 * away for future reference. This prevents different signals from
92 * trying to access the same static data at the same time.
94 * NOTE: We don't need this if we have POSIX.1 since we can install
95 * a signal mask automatically using sigaction()
97 void
98 fvwmSetSignalMask(int sigmask)
100 term_sigs = sigmask;
105 * fvwmGetSignalMask - get the set of signals that will terminate fvwm
107 * NOTE: We don't need this if we have POSIX.1 since we can install
108 * a signal mask automatically using sigaction()
111 fvwmGetSignalMask(void)
113 return term_sigs;
116 #endif
120 * fvwmSetTerminate - set the "end-of-execution" flag.
121 * This function should ONLY be called at the end of a
122 * signal handler. It is an integral part of the mechanism
123 * to stop system calls from blocking once the process is
124 * finished.
126 * NOTE: This is NOT a signal handler function in its own right!
128 void
129 fvwmSetTerminate(int sig)
131 BSD_BLOCK_SIGNALS;
133 isTerminated = true;
135 if (canJump)
137 canJump = false;
140 * This non-local jump is safe ONLY because we haven't called
141 * any non-reentrant functions in the short period where the
142 * "canJump" variable is true.
144 * NOTE: No need to restore the signal mask, since siglongjmp
145 * is designed to do that for us.
147 SIGLONGJMP(deadJump, SIG_DONE);
150 BSD_UNBLOCK_SIGNALS;
154 #ifdef HAVE_SELECT
156 * fvwmSelect - wrapper around the select() system call.
157 * This system call may block indefinitely. We don't want
158 * to block at all if the "terminate" flag is set - we
159 * just want it to fail as quickly as possible.
162 fvwmSelect(fd_set_size_t nfds,
163 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
164 struct timeval *timeout)
166 volatile int iRet = -1; /* This variable MUST NOT be in a register */
168 #ifdef C_ALLOCA
169 /* If we're using the C version of alloca, see if anything needs to be
170 * freed up.
172 alloca(0);
173 #endif
176 * Yes, we trash errno here, but you're only supposed to check
177 * errno immediately after a function fails anyway. If we fail,
178 * then it's because we received a signal. If we succeed, we
179 * shouldn't be checking errno. And if somebody calls us expecting
180 * us to preserve errno then that's their bug.
182 * NOTE: We mustn't call any function that might trash errno
183 * ourselves, except select() itself of course. I believe
184 * that sigsetjmp() does NOT trash errno.
186 errno = EINTR;
189 * Now initialise the non-local jump. Between here and the end of
190 * the routine (more-or-less) we must NOT call any non-reentrant
191 * functions! This is because we might need to abandon them half
192 * way through execution and return here!
194 if ( SIGSETJMP(deadJump, 1) == SIG_INIT )
197 * Activate the non-local jump. Between now and when we turn the
198 * jump off again, we must NOT call any non-reentrant functions
199 * because we could be interrupted halfway through ...
201 canJump = true;
204 * If we have already been told to terminate then we will not
205 * execute the select() because the flag will be set. If a
206 * "terminate" signal arrives between testing the flag and
207 * calling select() then we will jump back to the non-local
208 * jump point ...
210 if ( !isTerminated )
213 * The "die" signal will interrupt this system call:
214 * that IS the whole point, after all :-)
216 iRet = select(nfds,
217 SELECT_FD_SET_CAST readfds,
218 SELECT_FD_SET_CAST writefds,
219 SELECT_FD_SET_CAST exceptfds,
220 timeout);
224 * The non-local jump is about to go out of scope,
225 * so we must deactivate it. Note that the return-
226 * value from select() will be safely stored in the
227 * local variable before the jump is disabled.
229 canJump = false;
232 return iRet;
235 #endif /* HAVE_SELECT */