ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Async-Interrupt/Interrupt.pm
Revision: 1.12
Committed: Tue Jul 14 19:51:24 2009 UTC (14 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-0_042
Changes since 1.11: +1 -1 lines
Log Message:
0.042

File Contents

# Content
1 =head1 NAME
2
3 Async::Interrupt - allow C/XS libraries to interrupt perl asynchronously
4
5 =head1 SYNOPSIS
6
7 use Async::Interrupt;
8
9 =head1 DESCRIPTION
10
11 This module implements a single feature only of interest to advanced perl
12 modules, namely asynchronous interruptions (think "UNIX signals", which
13 are very similar).
14
15 Sometimes, modules wish to run code asynchronously (in another thread,
16 or from a signal handler), and then signal the perl interpreter on
17 certain events. One common way is to write some data to a pipe and use an
18 event handling toolkit to watch for I/O events. Another way is to send
19 a signal. Those methods are slow, and in the case of a pipe, also not
20 asynchronous - it won't interrupt a running perl interpreter.
21
22 This module implements asynchronous notifications that enable you to
23 signal running perl code from another thread, asynchronously, and
24 sometimes even without using a single syscall.
25
26 =head2 USAGE SCENARIOS
27
28 =over 4
29
30 =item Race-free signal handling
31
32 There seems to be no way to do race-free signal handling in perl: to
33 catch a signal, you have to execute Perl code, and between entering the
34 interpreter C<select> function (or other blocking functions) and executing
35 the select syscall is a small but relevant timespan during which signals
36 will be queued, but perl signal handlers will not be executed and the
37 blocking syscall will not be interrupted.
38
39 You can use this module to bind a signal to a callback while at the same
40 time activating an event pipe that you can C<select> on, fixing the race
41 completely.
42
43 This can be used to implement the signal hadling in event loops,
44 e.g. L<AnyEvent>, L<POE>, L<IO::Async::Loop> and so on.
45
46 =item Background threads want speedy reporting
47
48 Assume you want very exact timing, and you can spare an extra cpu core
49 for that. Then you can run an extra thread that signals your perl
50 interpreter. This means you can get a very exact timing source while your
51 perl code is number crunching, without even using a syscall to communicate
52 between your threads.
53
54 For example the deliantra game server uses a variant of this technique
55 to interrupt background processes regularly to send map updates to game
56 clients.
57
58 L<IO::AIO> and L<BDB> could also use this to speed up result reporting.
59
60 =item Speedy event loop invocation
61
62 One could use this module e.g. in L<Coro> to interrupt a running coro-thread
63 and cause it to enter the event loop.
64
65 Or one could bind to C<SIGIO> and tell some important sockets to send this
66 signal, causing the event loop to be entered to reduce network latency.
67
68 =back
69
70 =head2 HOW TO USE
71
72 You can use this module by creating an C<Async::Interrupt> object for each
73 such event source. This object stores a perl and/or a C-level callback
74 that is invoked when the C<Async::Interrupt> object gets signalled. It is
75 executed at the next time the perl interpreter is running (i.e. it will
76 interrupt a computation, but not an XS function or a syscall).
77
78 You can signal the C<Async::Interrupt> object either by calling it's C<<
79 ->signal >> method, or, more commonly, by calling a C function. There is
80 also the built-in (POSIX) signal source.
81
82 The C<< ->signal_func >> returns the address of the C function that is to
83 be called (plus an argument to be used during the call). The signalling
84 function also takes an integer argument in the range SIG_ATOMIC_MIN to
85 SIG_ATOMIC_MAX (guaranteed to allow at least 0..127).
86
87 Since this kind of interruption is fast, but can only interrupt a
88 I<running> interpreter, there is optional support for signalling a pipe
89 - that means you can also wait for the pipe to become readable (e.g. via
90 L<EV> or L<AnyEvent>). This, of course, incurs the overhead of a C<read>
91 and C<write> syscall.
92
93 =over 4
94
95 =cut
96
97 package Async::Interrupt;
98
99 use common::sense;
100
101 BEGIN {
102 # the next line forces initialisation of internal
103 # signal handling # variables
104 $SIG{KILL} = sub { };
105
106 our $VERSION = '0.042';
107
108 require XSLoader;
109 XSLoader::load ("Async::Interrupt", $VERSION);
110 }
111
112 our $DIED = sub { warn "$@" };
113
114 =item $async = new Async::Interrupt key => value...
115
116 Creates a new Async::Interrupt object. You may only use async
117 notifications on this object while it exists, so you need to keep a
118 reference to it at all times while it is used.
119
120 Optional constructor arguments include (normally you would specify at
121 least one of C<cb> or C<c_cb>).
122
123 =over 4
124
125 =item cb => $coderef->($value)
126
127 Registers a perl callback to be invoked whenever the async interrupt is
128 signalled.
129
130 Note that, since this callback can be invoked at basically any time, it
131 must not modify any well-known global variables such as C<$/> without
132 restoring them again before returning.
133
134 The exceptions are C<$!> and C<$@>, which are saved and restored by
135 Async::Interrupt.
136
137 If the callback should throw an exception, then it will be caught,
138 and C<$Async::Interrupt::DIED> will be called with C<$@> containing
139 the exception. The default will simply C<warn> about the message and
140 continue.
141
142 =item c_cb => [$c_func, $c_arg]
143
144 Registers a C callback the be invoked whenever the async interrupt is
145 signalled.
146
147 The C callback must have the following prototype:
148
149 void c_func (pTHX_ void *c_arg, int value);
150
151 Both C<$c_func> and C<$c_arg> must be specified as integers/IVs, and
152 C<$value> is the C<value> passed to some earlier call to either C<$signal>
153 or the C<signal_func> function.
154
155 Note that, because the callback can be invoked at almost any time, you
156 have to be careful at saving and restoring global variables that Perl
157 might use (the exception is C<errno>, which is saved and restored by
158 Async::Interrupt). The callback itself runs as part of the perl context,
159 so you can call any perl functions and modify any perl data structures (in
160 which case the requirements set out for C<cb> apply as well).
161
162 =item signal => $signame_or_value
163
164 When this parameter is specified, then the Async::Interrupt will hook the
165 given signal, that is, it will effectively call C<< ->signal (0) >> each time
166 the given signal is caught by the process.
167
168 Only one async can hook a given signal, and the signal will be restored to
169 defaults when the Async::Interrupt object gets destroyed.
170
171 =item pipe => [$fileno_or_fh_for_reading, $fileno_or_fh_for_writing]
172
173 Specifies two file descriptors (or file handles) that should be signalled
174 whenever the async interrupt is signalled. This means a single octet will
175 be written to it, and before the callback is being invoked, it will be
176 read again. Due to races, it is unlikely but possible that multiple octets
177 are written. It is required that the file handles are both in nonblocking
178 mode.
179
180 You can get a portable pipe and set non-blocking mode portably by using
181 e.g. L<AnyEvent::Util> from the L<AnyEvent> distribution.
182
183 It is also possible to pass in a linux eventfd as both read and write
184 handle (which is faster than a pipe).
185
186 The object will keep a reference to the file handles.
187
188 This can be used to ensure that async notifications will interrupt event
189 frameworks as well.
190
191 =back
192
193 =cut
194
195 sub new {
196 my ($class, %arg) = @_;
197
198 bless \(_alloc $arg{cb}, @{$arg{c_cb}}[0,1], @{$arg{pipe}}[0,1], $arg{signal}), $class
199 }
200
201 =item ($signal_func, $signal_arg) = $async->signal_func
202
203 Returns the address of a function to call asynchronously. The function has
204 the following prototype and needs to be passed the specified C<$c_arg>,
205 which is a C<void *> cast to C<IV>:
206
207 void (*signal_func) (void *signal_arg, int value)
208
209 An example call would look like:
210
211 signal_func (signal_arg, 0);
212
213 The function is safe to call from within signal and thread contexts, at
214 any time. The specified C<value> is passed to both C and Perl callback.
215
216 C<$value> must be in the valid range for a C<sig_atomic_t> (0..127 is
217 portable).
218
219 If the function is called while the Async::Interrupt object is already
220 signaled but before the callbacks are being executed, then the stored
221 C<value> is either the old or the new one. Due to the asynchronous
222 nature of the code, the C<value> can even be passed to two consecutive
223 invocations of the callback.
224
225 =item $async->signal ($value=0)
226
227 This signals the given async object from Perl code. Semi-obviously, this
228 will instantly trigger the callback invocation.
229
230 C<$value> must be in the valid range for a C<sig_atomic_t> (0..127 is
231 portable).
232
233 =item $async->block
234
235 =item $async->unblock
236
237 Sometimes you need a "critical section" of code that will not be
238 interrupted by an Async::Interrupt. This can be implemented by calling C<<
239 $async->block >> before the critical section, and C<< $async->unblock >>
240 afterwards.
241
242 Note that there must be exactly one call of C<unblock> for every previous
243 call to C<block> (i.e. calls can nest).
244
245 Since ensuring this in the presence of exceptions and threads is
246 usually more difficult than you imagine, I recommend using C<<
247 $async->scoped_block >> instead.
248
249 =item $async->scope_block
250
251 This call C<< $async->block >> and installs a handler that is called when
252 the current scope is exited (via an exception, by canceling the Coro
253 thread, by calling last/goto etc.).
254
255 This is the recommended (and fastest) way to implement critical sections.
256
257 =item $async->pipe_enable
258
259 =item $async->pipe_disable
260
261 Enable/disable signalling the pipe when the interrupt occurs (default is
262 enabled). Writing to a pipe is relatively expensive, so it can be disabled
263 when you know you are not waiting for it (for example, with L<EV> you
264 could disable the pipe in a check watcher, and enable it in a prepare
265 watcher).
266
267 Note that when C<fd_disable> is in effect, no attempt to read from the
268 pipe will be done.
269
270 =cut
271
272 1;
273
274 =back
275
276 =head1 EXAMPLE
277
278 There really should be a complete C/XS example. Bug me about it. Better
279 yet, create one.
280
281 =head1 IMPLEMENTATION DETAILS AND LIMITATIONS
282
283 This module works by "hijacking" SIGKILL, which is guaranteed to always
284 exist, but also cannot be caught, so is always available.
285
286 Basically, this module fakes the occurance of a SIGKILL signal and
287 then intercepts the interpreter handling it. This makes normal signal
288 handling slower (probably unmeasurably, though), but has the advantage
289 of not requiring a special runops function, nor slowing down normal perl
290 execution a bit.
291
292 It assumes that C<sig_atomic_t> and C<int> are both async-safe to modify
293 (C<sig_atomic_> is used by this module, and perl itself uses C<int>, so we
294 can assume that this is quite portable, at least w.r.t. signals).
295
296 =head1 AUTHOR
297
298 Marc Lehmann <schmorp@schmorp.de>
299 http://home.schmorp.de/
300
301 =cut
302