1Sys::SigAction(3) User Contributed Perl Documentation Sys::SigAction(3)
2
3
4
6 Sys::SigAction - Perl extension for Consistent Signal Handling
7
9 #do something non-interrupt able
10 use Sys::SigAction qw( set_sig_handler );
11 {
12 my $h = set_sig_handler( 'INT' ,'mysubname' ,{ flags => SA_RESTART } );
13 ... do stuff non-interrupt able
14 } #signal handler is reset when $h goes out of scope
15
16 or
17
18 #timeout a system call:
19 use Sys::SigAction qw( set_sig_handler );
20 eval {
21 my $h = set_sig_handler( 'ALRM' ,\&mysubname ,{ mask=>[ 'ALRM' ] ,safe=>1 } );
22 eval {
23 alarm(2)
24 ... do something you want to timeout
25 alarm(0);
26 };
27 alarm(0);
28 die $@ if $@;
29 }; #signal handler is reset when $h goes out of scope
30 if ( $@ ) ...
31
32 or
33
34 use Sys::SigAction;
35 my $alarm = 0;
36 eval {
37 my $h = Sys::SigAction::set_sig_handler( 'ALRM' ,sub { $alarm = 1; } );
38 eval {
39 alarm(2)
40 ... do something you want to timeout
41 alarm(0);
42 };
43 alarm(0);
44 die $@ if $@;
45 }; #signal handler is reset when $h goes out of scope
46 if ( $@ or $alarm ) ...
47
48 or
49
50 use Sys::SigAction;
51 my $alarm = 0;
52 Sys::SigAction::set_sig_handler( 'TERM' ,sub { "DUMMY" } );
53 #code from here on uses new handler.... (old handler is forgotten)
54
55 or
56
57 use Sys::SigAction qw( timeout_call );
58 if ( timeout_call( 5 ,sub { $retval = DoSomething( @args ); } )
59 {
60 print "DoSomething() timed out\n" ;
61 }
62
63 or
64
65 #use a floating point (fractional seconds) in timeout_call
66 use Sys::SigAction qw( timeout_call );
67 if ( timeout_call( 0.1 ,sub { $retval = DoSomething( @args ); } )
68 {
69 print "DoSomething() timed out\n" ;
70 }
71
73 This module implements set_sig_handler(), which sets up a signal
74 handler and (optionally) returns an object which causes the signal
75 handler to be reset to the previous value, when it goes out of scope.
76
77 Also implemented is timeout_call() which takes a timeout value, a code
78 reference and optional arguments, and executes the code reference
79 wrapped with an alarm timeout. timeout_call accepts seconds in floating
80 point format, so you can time out call with a resolution of 0.000001
81 seconds. If "Time::HiRes" is not loadable or Time::HiRes::ualarm() does
82 not work, then the factional part of the time value passed to
83 timeout_call() will be raise to the next higher integer with
84 POSIX::ceil(). This means that the shortest a timeout can be in 1
85 second.
86
87 Finally, two convenience routines are defined which allow one to get
88 the signal name from the number -- sig_name(), and get the signal
89 number from the name -- sig_number().
90
92 Prior to version 5.8.0 perl implemented 'unsafe' signal handling. The
93 reason it is consider unsafe, is that there is a risk that a signal
94 will arrive, and be handled while perl is changing internal data
95 structures. This can result in all kinds of subtle and not so subtle
96 problems. For this reason it has always been recommended that one do
97 as little as possible in a signal handler, and only variables that
98 already exist be manipulated.
99
100 Perl 5.8.0 and later versions implements 'safe' signal handling on
101 platforms which support the POSIX sigaction() function. This is
102 accomplished by having perl note that a signal has arrived, but
103 deferring the execution of the signal handler until such time as it is
104 safe to do so. Unfortunately these changes can break some existing
105 scripts, if they depended on a system routine being interrupted by the
106 signal's arrival. The perl 5.8.0 implementation was modified further
107 in version 5.8.2.
108
109 From the perl 5.8.2 perlvar man page:
110
111 The default delivery policy of signals changed in Perl 5.8.0
112 from immediate (also known as "unsafe") to deferred, also
113 known as "safe signals".
114
115 The implementation of this changed the "sa_flags" with which the signal
116 handler is installed by perl, and it causes some system routines (like
117 connect()) to return EINTR, instead of another error when the signal
118 arrives. The problem comes when the code that made the system call
119 sees the EINTR code and decides it's going to call it again before
120 returning. Perl doesn't do this but some libraries do, including for
121 instance, the Oracle OCI library.
122
123 Thus the 'deferred signal' approach (as implemented by default in perl
124 5.8 and later) results in some system calls being retried prior to the
125 signal handler being called by perl. This breaks timeout logic for
126 DBD-Oracle which works with earlier versions of perl. This can be
127 particularly vexing, when, for instance, the host on which a database
128 resides is not available: "DBI->connect()" hangs for minutes before
129 returning an error (and cannot even be interrupted with control-C, even
130 when the intended timeout is only seconds). This is because SIGINT
131 appears to be deferred as well. The result is that it is impossible to
132 implement open timeouts with code that looks like this in perl 5.8.0
133 and later:
134
135 eval {
136 eval {
137 local $SIG{ALRM} = sub { die "timeout" };
138 alarm 2;
139 $sth = DBI->connect(...);
140 alarm 0;
141 };
142 alarm 0;
143 die if $@;
144 };
145
146 Or as the author of bug #50628 pointed out, might probably better be
147 written as:
148
149 eval {
150 local $SIG{ALRM} = sub { die "timeout" };
151 eval {
152 alarm 2;
153 $sth = DBI->connect(...);
154 alarm 0;
155 };
156 alarm 0;
157 die if $@;
158 };
159
160 The solution, if your system has the POSIX sigaction() function, is to
161 use perl's POSIX::sigaction() to install the signal handler. With
162 sigaction(), one gets control over both the signal mask, and the
163 "sa_flags" that are used to install the handler. Further, with perl
164 5.8.2 and later, a 'safe' switch is provided which can be used to ask
165 for safe(r) signal handling.
166
167 Using sigaction() ensures that the system call won't be resumed after
168 it's interrupted, so long as die is called within the signal handler.
169 This is no longer the case when one uses $SIG{name} to set signal
170 handlers in perls >= 5.8.0.
171
172 The usage of sigaction() is not well documented however, and in perl
173 versions less than 5.8.0, it does not work at all. (But that's OK,
174 because just setting $SIG does work in that case.) Using sigaction()
175 requires approximately 4 or 5 lines of code where previously one only
176 had to set a code reference into the %SIG hash.
177
178 Unfortunately, at least with perl 5.8.0, the result is that doing this
179 effectively reverts to the 'unsafe' signals behavior. It is not clear
180 whether this would be the case in perl 5.8.2, since the safe flag can
181 be used to ask for safe signal handling. I suspect this separates the
182 logic which uses the "sa_flags" to install the handler, and whether
183 deferred signal handling is used.
184
185 The reader should also note, that the behavior of the 'safe' attribute
186 is not consistent with what this author expected. Specifically, it
187 appears to disable signal masking. This can be examined further in the
188 t/safe.t and the t/mask.t regression tests. Never-the-less,
189 Sys::SigAction provides an easy mechanism for the user to recover the
190 pre-5.8.0 behavior for signal handling, and the mask attribute clearly
191 works. (see t/mask.t) If one is looking for specific safe signal
192 handling behavior that is considered broken, and the breakage can be
193 demonstrated, then a patch to t/safe.t would be most welcome.
194
195 This module wraps up the POSIX:: routines and objects necessary to call
196 sigaction() in a way that is as efficient from a coding perspective as
197 just setting a localized $SIG{SIGNAL} with a code reference. Further,
198 the user has control over the "sa_flags" passed to sigaction(). By
199 default, if no additional args are passed to sigaction(), then the
200 signal handler will be called when a signal (such as SIGALRM) is
201 delivered.
202
203 Since sigaction() is not fully functional in perl versions less than
204 5.8, this module implements equivalent behavior using the standard %SIG
205 array. The version checking and implementation of the 'right' code is
206 handled by this module, so the user does not have to write perl version
207 dependent code. The attrs hashref argument to set_sig_handler() is
208 silently ignored, in perl versions less than 5.8. When this module was
209 developed it was tested on perl 5.005 on solaris. That was in 2004.
210 Now only perl versions >= 5.6 are supported. If you want this to work
211 on perl 5.5 you will have comment out "use warnings" everywhere.
212
213 It is hoped that with the use of this module, your signal handling
214 behavior can be coded in a way that does not change from one perl
215 version to the next, and that sigaction() will be easier for you to
216 use.
217
219 CPAN bug #50628 which was filed against Sys::SigAction-0.11 noting that
220 the sample code was "buggy" because the evals that wrapped the code we
221 wanted to timeout might die for an unanticipated reason, before the
222 alarm could be cleared. In that case, as the bug writer noted, if the
223 alarm expires before the final alarm(0) can be called, either the code
224 will completely die because there is no SIGALRM handler in place to
225 catch the signal, or the wrong handler (not the local handler) will be
226 called.
227
228 All the code samples in this module have been modified to account for
229 this. Additionally we have made the same change in timeout_call()
230 which could have exhibited this behavior, though the AUTHOR never
231 knowing experienced it.
232
234 set_sig_handler()
235 $sig ,$handler ,$attrs
236
237 Install a new signal handler and (if not called in a void context)
238 returning a Sys::SigAction object containing the old signal handler,
239 which will be restored on object destruction.
240
241 $sig is a signal name (without the 'SIG') or number.
242
243 $handler is either the name (string) of a signal handler
244 function or a subroutine CODE reference.
245
246 $attrs if defined is a hash reference containing the
247 following keys:
248
249 flags => the flags the passed sigaction
250
251 ex: SA_RESTART (defined in your signal.h)
252
253 mask => the array reference: signals you
254 do not want delivered while the signal
255 handler is executing
256
257 ex: [ SIGINT SIGUSR1 ] or
258 ex: [ qw( INT USR1 ]
259
260 safe => A boolean value requesting 'safe' signal
261 handling (only in 5.8.2 and greater)
262 earlier versions will issue a warning if
263 you use this
264
265 NOTE: This breaks the signal masking
266
267 timeout_call()
268 $timeout, $coderef, @args
269
270 Given a code reference, and a timeout value (in seconds),
271 timeout_call() will (in an eval) setup a signal handler for SIGALRM
272 (which will die), set an alarm clock, and execute the code reference
273 with optional arguments @args. $timeout (seconds) may be expressed as a
274 floating point number.
275
276 If Time::HiRes is present and useable, timeout_call() can be used with
277 a timer resolution of 0.000001 seconds. If HiRes is not loadable,
278 Sys::SigAction will "do the right thing" and convert the factional
279 seconds to the next higher integer value using the posix ceil()
280 function.
281
282 If the alarm goes off the code will be interrupted. The alarm is
283 canceled if the code returns before the alarm is fired. The routine
284 returns true if the code being executed timed out. (was interrupted).
285 Exceptions thrown by the code executed are propagated out.
286
287 The original signal handler is restored, prior to returning to the
288 caller.
289
290 sig_alarm()
291 ex:
292
293 sig_alarm( 1.2 );
294
295 sig_alarm() is a drop in replacement for the standard alarm() function.
296 The argument may be expressed as a floating point number.
297
298 If Time::HiRes is present and useable, the alarm timers will be set to
299 the floating point value with a resolution of 0.000001 seconds. If
300 Time::HiRes is not available then the a fractional value in the
301 argument will be raised to the next higher integer value.
302
303 sig_name()
304 Return the signal name (string) from a signal number.
305
306 ex:
307
308 sig_name( SIGINT ) returns 'INT'
309
310 sig_number()
311 Return the signal number (integer) from a signal name (minus the SIG
312 part).
313
314 ex:
315
316 sig_number( 'INT' ) returns the integer value of SIGINT;
317
319 Sys::SigAction works just fine on perls built with multithread support
320 in single threaded perl applications. However, please note that using
321 Signals in a multi-thread perl application is unsupported.
322
323 Read the following from perldoc perlthrtut:
324
325 ... mixing signals and threads may be problematic.
326 Implementations are platform-dependent, and even the POSIX semantics
327 may not be what you expect (and Perl doesn't even give you the full
328 POSIX API). For example, there is no way to guarantee that a signal
329 sent to a multi-threaded Perl application will get intercepted by
330 any particular thread.
331
332 That said, perl documentation for perl threading discusses a a way of
333 emulating signals in multi-threaded applications, when safe signals is
334 in effect. See perldoc threads and search for THREAD SIGNALLING. I
335 have no test of multithreading and this module. If you think they
336 could be used compatibly and would provide value, patches are welcome.
337
339 Lincoln A. Baxter <lab-at-lincolnbaxter-dot-com>
340
342 Copyright (c) 2004-2016 Lincoln A. Baxter
343 All rights reserved.
344
345 You may distribute under the terms of either the GNU General Public
346 License or the Artistic License, as specified in the Perl README file,
347
349 perldoc perlvar
350 perldoc POSIX
351
352
353
354perl v5.36.0 2023-01-20 Sys::SigAction(3)