Skip Menu |

This queue is for tickets about the IO-Async CPAN distribution.

Report information
The Basics
Id: 128588
Status: resolved
Priority: 0/
Queue: IO-Async

People
Owner: Nobody in particular
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.72
Fixed in: 0.75



Subject: ->post_fork confuses sigpipe
->post_fork ought to create a new signal pipe, as if the parent and child share one Bad Things will happen -- Paul Evans
On Fri Feb 22 08:02:38 2019, PEVANS wrote: Show quoted text
> ->post_fork ought to create a new signal pipe, as if the parent and > child share one Bad Things will happen
Fixed. Hopefully. -- Paul Evans
Subject: rt128588.patch
=== modified file 'lib/IO/Async/Loop.pm' --- old/lib/IO/Async/Loop.pm 2019-11-23 17:39:12 +0000 +++ new/lib/IO/Async/Loop.pm 2019-11-23 18:27:10 +0000 @@ -594,7 +594,9 @@ sub post_fork { - # empty + my $self = shift; + + IO::Async::OS->post_fork( $self ); } ########### === modified file 'lib/IO/Async/LoopTests.pm' --- old/lib/IO/Async/LoopTests.pm 2019-06-27 17:51:07 +0000 +++ new/lib/IO/Async/LoopTests.pm 2019-11-23 18:27:10 +0000 @@ -580,7 +580,7 @@ =cut -use constant count_tests_signal => 14; +use constant count_tests_signal => 15; sub run_tests_signal { unless( IO::Async::OS->HAVE_SIGNALS ) { @@ -650,6 +650,17 @@ ok( exception { $loop->attach_signal( 'this signal name does not exist', sub {} ) }, 'Bad signal name fails' ); + + undef $caught; + $loop->attach_signal( TERM => sub { $caught++ } ); + + $loop->post_fork; + + kill SIGTERM, $$; + + $loop->loop_once( 0.1 ); + + is( $caught, 1, '$caught SIGTERM after ->post_fork' ); } =head2 idle === modified file 'lib/IO/Async/OS.pm' --- old/lib/IO/Async/OS.pm 2019-06-27 17:51:07 +0000 +++ new/lib/IO/Async/OS.pm 2019-11-23 18:27:10 +0000 @@ -548,6 +548,34 @@ =cut +sub _setup_sigpipe +{ + my $self = shift; + my ( $loop ) = @_; + + require IO::Async::Handle; + + my ( $reader, $sigpipe ) = $self->pipepair or croak "Cannot pipe() - $!"; + $_->blocking( 0 ) for $reader, $sigpipe; + + $loop->{os}{sigpipe} = $sigpipe; + + my $sigwatch = $loop->{os}{sigwatch}; + + $loop->add( $loop->{os}{sigpipe_reader} = IO::Async::Handle->new( + notifier_name => "sigpipe", + read_handle => $reader, + on_read_ready => sub { + sysread $reader, my $buffer, 8192 or return; + foreach my $signum ( unpack "I*", $buffer ) { + $sigwatch->{$signum}->() if $sigwatch->{$signum}; + } + }, + ) ); + + return $sigpipe; +} + sub loop_watch_signal { my $self = shift; @@ -559,26 +587,7 @@ my $signum = $self->signame2num( $signal ); my $sigwatch = $loop->{os}{sigwatch} ||= {}; # {$num} = $code - my $sigpipe; - unless( $sigpipe = $loop->{os}{sigpipe} ) { - require IO::Async::Handle; - - ( my $reader, $sigpipe ) = $self->pipepair or croak "Cannot pipe() - $!"; - $_->blocking( 0 ) for $reader, $sigpipe; - - $loop->{os}{sigpipe} = $sigpipe; - - $loop->add( $loop->{os}{sigpipe_reader} = IO::Async::Handle->new( - notifier_name => "sigpipe", - read_handle => $reader, - on_read_ready => sub { - sysread $reader, my $buffer, 8192 or return; - foreach my $signum ( unpack "I*", $buffer ) { - $sigwatch->{$signum}->() if $sigwatch->{$signum}; - } - }, - ) ); - } + my $sigpipe = $loop->{os}{sigpipe} // $self->_setup_sigpipe( $loop ); my $signum_str = pack "I", $signum; $SIG{$signal} = sub { syswrite $sigpipe, $signum_str }; @@ -613,6 +622,26 @@ return 0 .. OPEN_MAX_FD; } +sub post_fork +{ + my $self = shift; + my ( $loop ) = @_; + + if( $loop->{os}{sigpipe} ) { + $loop->remove( $loop->{os}{sigpipe_reader} ); + undef $loop->{os}{sigpipe}; + + my $sigwatch = $loop->{os}{sigwatch}; + + foreach my $signal ( keys %SIG ) { + my $signum = $self->signame2num( $signal ) or next; + my $code = $sigwatch->{$signum} or next; + + $self->loop_watch_signal( $loop, $signal, $code ); + } + } +} + =head1 AUTHOR Paul Evans <leonerd@leonerd.org.uk>