… | |
… | |
91 | I<running> interpreter, there is optional support for signalling a pipe |
91 | I<running> interpreter, there is optional support for signalling a pipe |
92 | - that means you can also wait for the pipe to become readable (e.g. via |
92 | - that means you can also wait for the pipe to become readable (e.g. via |
93 | L<EV> or L<AnyEvent>). This, of course, incurs the overhead of a C<read> |
93 | L<EV> or L<AnyEvent>). This, of course, incurs the overhead of a C<read> |
94 | and C<write> syscall. |
94 | and C<write> syscall. |
95 | |
95 | |
|
|
96 | =head1 USAGE EXAMPLES |
|
|
97 | |
|
|
98 | =head2 Async::Interrupt to implement race-free signal handling |
|
|
99 | |
|
|
100 | This example uses a single event pipe for all signals, and one |
|
|
101 | Async::Interrupt per signal. |
|
|
102 | |
|
|
103 | First, create the event pipe and hook it into the event loop (this code is |
|
|
104 | actually what L<AnyEvent> uses itself): |
|
|
105 | |
|
|
106 | $SIGPIPE = new Async::Interrupt::EventPipe; |
|
|
107 | $SIGPIPE_W = AnyEvent->io ( |
|
|
108 | fh => $SIGPIPE->fileno, |
|
|
109 | poll => "r", |
|
|
110 | cb => \&_signal_check, |
|
|
111 | ); |
|
|
112 | |
|
|
113 | Then, for each signal to hook, create an Async::Interrupt object. The |
|
|
114 | callback just sets a global variable, as we are only interested in |
|
|
115 | synchronous signals (i.e. when the event loop polls), which is why the |
|
|
116 | pipe draining is not done automatically. |
|
|
117 | |
|
|
118 | my $interrupt = new Async::Interrupt |
|
|
119 | cb => sub { undef $SIGNAL_RECEIVED{$signum} } |
|
|
120 | signal => $signal, |
|
|
121 | pipe => [$SIGPIPE_R->filenos], |
|
|
122 | pipe_autodrain => 0, |
|
|
123 | ; |
|
|
124 | |
|
|
125 | Finally, the I/O callback for the event pipe handles the signals: |
|
|
126 | |
|
|
127 | sub _signal_check { |
|
|
128 | # drain the pipe first |
|
|
129 | $SIGPIPE->drain; |
|
|
130 | |
|
|
131 | # two loops, just to be sure |
|
|
132 | while (%SIGNAL_RECEIVED) { |
|
|
133 | for (keys %SIGNAL_RECEIVED) { |
|
|
134 | delete $SIGNAL_RECEIVED{$_}; |
|
|
135 | warn "signal $_ received\n"; |
|
|
136 | } |
|
|
137 | } |
|
|
138 | } |
|
|
139 | |
|
|
140 | |
|
|
141 | |
96 | =head1 THE Async::Interrupt CLASS |
142 | =head1 THE Async::Interrupt CLASS |
97 | |
143 | |
98 | =over 4 |
144 | =over 4 |
99 | |
145 | |
100 | =cut |
146 | =cut |
… | |
… | |
376 | This only works when the pipe was created by Async::Interrupt. |
422 | This only works when the pipe was created by Async::Interrupt. |
377 | |
423 | |
378 | Async::Interrupt ensures that the reading file descriptor does not change |
424 | Async::Interrupt ensures that the reading file descriptor does not change |
379 | it's value. |
425 | it's value. |
380 | |
426 | |
|
|
427 | =item $signum = Async::Interrupt::sig2num $signame_or_number |
|
|
428 | |
|
|
429 | =item $signame = Async::Interrupt::sig2name $signame_or_number |
|
|
430 | |
|
|
431 | These two convenience functions simply convert a signal name or number to |
|
|
432 | the corresponding name or number. They are not used by this module and |
|
|
433 | exist just because perl doesn't have a nice way to do this on its own. |
|
|
434 | |
|
|
435 | They will return C<undef> on illegal names or numbers. |
|
|
436 | |
381 | =back |
437 | =back |
382 | |
438 | |
383 | =head1 THE Async::Interrupt::EventPipe CLASS |
439 | =head1 THE Async::Interrupt::EventPipe CLASS |
384 | |
440 | |
385 | Pipes are the predominent utility to make asynchronous signals |
441 | Pipes are the predominent utility to make asynchronous signals |