Thread: [poe-commits] poe/POE/Pipe OneWay.pm,1.10,1.11 TwoWay.pm,1.13,1.14
Brought to you by:
rcaputo
From: <rc...@us...> - 2003-07-16 17:00:28
|
Update of /cvsroot/poe/poe/POE/Pipe In directory sc8-pr-cvs1:/tmp/cvs-serv3431/POE/Pipe Modified Files: OneWay.pm TwoWay.pm Log Message: Leif Gustafson discovered a nasty little bug in POE::Pipe::TwoWay that was triggered by the recent changes to POE::Wheel::Run... but only on cygwin! What a nasty confluence of circumstance. Thank you, Leif. This patch should help that a lot, and it finally cleans up the really messy RUNNING_IN_HELL stuff in the pipe classes. Index: OneWay.pm =================================================================== RCS file: /cvsroot/poe/poe/POE/Pipe/OneWay.pm,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** OneWay.pm 22 Jun 2002 06:15:33 -0000 1.10 --- OneWay.pm 16 Jul 2003 17:00:25 -0000 1.11 *************** *** 18,26 **** sub DEBUG () { 0 } - sub RUNNING_IN_HELL () { $^O eq 'MSWin32' or $^O eq 'MacOS' } - - # This flag is set true/false after the first attempt at using plain - # INET sockets as pipes. - my $can_run_socket = undef; sub new { --- 18,21 ---- *************** *** 35,77 **** my $b_write = gensym(); ! # Try the pipe if no preferred conduit type is specified, or if the ! # specified conduit type is 'pipe'. ! if ( (not RUNNING_IN_HELL) and ! ( (not defined $conduit_type) or ! ($conduit_type eq 'pipe') ! ) and ! ( not defined $can_run_socket ) ! ) { eval { pipe($a_read, $b_write) or die "pipe failed: $!"; }; ! # Pipe succeeded. ! unless (length $@) { ! DEBUG and do { ! warn "using a pipe"; ! warn "ar($a_read) bw($b_write)\n"; ! }; ! ! # Turn off buffering. POE::Kernel does this for us, but ! # someone might want to use the pipe class elsewhere. ! select((select($b_write), $| = 1)[0]); ! return($a_read, $b_write); ! } ! elsif (DEBUG) { ! warn "pipe failed: $@"; } - } ! # Try UNIX-domain socketpair if no preferred conduit type is ! # specified, or if the specified conduit type is 'socketpair'. ! if ( (not RUNNING_IN_HELL) and ! ( (not defined $conduit_type) or ! ($conduit_type eq 'socketpair') ! ) and ! ( not defined $can_run_socket ) ! ) { eval { socketpair($a_read, $b_write, AF_UNIX, SOCK_STREAM, PF_UNSPEC) --- 30,79 ---- my $b_write = gensym(); ! if (defined $conduit_type) { ! ($a_read, $b_write) = $self->_try_type($conduit_type, $a_read, $b_write); ! return ($a_read, $b_write) if $a_read; ! } + while (my $try_type = $self->get_next_preference()) { + ($a_read, $b_write) = $self->_try_type($try_type, $a_read, $b_write); + return ($a_read, $b_write) if $a_read; + $self->shift_preference(); + } + + # There's nothing left to try. + DEBUG and warn "nothing worked"; + return (undef, undef, undef, undef); + } + + # Try a pipe by type. + + sub _try_type { + my ($self, $type, $a_read, $b_write) = @_; + + # Try a pipe(). + if ($type eq "pipe") { eval { pipe($a_read, $b_write) or die "pipe failed: $!"; }; ! # Pipe failed. ! if (length $@) { ! warn "pipe failed: $@" if DEBUG; ! return (undef, undef); } ! DEBUG and do { ! warn "using a pipe"; ! warn "ar($a_read) bw($b_write)\n"; ! }; ! ! # Turn off buffering. POE::Kernel does this for us, but ! # someone might want to use the pipe class elsewhere. ! select((select($b_write), $| = 1)[0]); ! return($a_read, $b_write); ! } + # Try a UNIX-domain socketpair. + if ($type eq "socketpair") { eval { socketpair($a_read, $b_write, AF_UNIX, SOCK_STREAM, PF_UNSPEC) *************** *** 79,148 **** }; ! # Socketpair succeeded. ! unless (length $@) { ! DEBUG and do { ! warn "using a UNIX domain socketpair"; ! warn "ar($a_read) bw($b_write)\n"; ! }; ! ! # It's one-way, so shut down the unused directions. ! shutdown($a_read, 1); ! shutdown($b_write, 0); ! ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($b_write), $| = 1)[0]); ! return($a_read, $b_write); ! } ! elsif (DEBUG) { ! warn "socketpair failed: $@"; } - } ! # Try a pair of plain INET sockets if no preffered conduit type is ! # specified, or if the specified conduit type is 'inet'. ! if ( ( RUNNING_IN_HELL or ! (not defined $conduit_type) or ! ($conduit_type eq 'inet') ! ) and ! ( $can_run_socket or (not defined $can_run_socket) ) ! ) { ! # Try using a pair of plain INET domain sockets. eval { ($a_read, $b_write) = $self->make_socket(); }; ! # Sockets worked. ! unless (length $@) { ! DEBUG and do { ! warn "using a plain INET socket"; ! warn "ar($a_read) bw($b_write)\n"; ! }; ! ! # Try sockets more often. ! $can_run_socket = 1; ! # It's one-way, so shut down the unused directions. ! shutdown($a_read, 1); ! shutdown($b_write, 0); ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($b_write), $| = 1)[0]); ! return($a_read, $b_write); ! } ! # Sockets failed. Don't try them again. ! else { ! DEBUG and warn "make_socket failed: $@"; ! $can_run_socket = 0; ! } } # There's nothing left to try. ! DEBUG and warn "nothing worked"; ! return(undef, undef); } --- 81,133 ---- }; ! if (length $@) { ! warn "socketpair failed: $@" if DEBUG; ! return (undef, undef); } ! DEBUG and do { ! warn "using a UNIX domain socketpair"; ! warn "ar($a_read) bw($b_write)\n"; ! }; ! # It's one-way, so shut down the unused directions. ! shutdown($a_read, 1); ! shutdown($b_write, 0); ! ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($b_write), $| = 1)[0]); ! return($a_read, $b_write); ! } + # Try a pair of plain INET sockets. + if ($type eq "inet") { eval { ($a_read, $b_write) = $self->make_socket(); }; ! if (length $@) { ! warn "make_socket failed: $@" if DEBUG; ! return (undef, undef); ! } ! DEBUG and do { ! warn "using a plain INET socket"; ! warn "ar($a_read) bw($b_write)\n"; ! }; ! # It's one-way, so shut down the unused directions. ! shutdown($a_read, 1); ! shutdown($b_write, 0); ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($b_write), $| = 1)[0]); ! return($a_read, $b_write); } # There's nothing left to try. ! DEBUG and warn "unknown OneWay socket type ``$type''"; ! return; } Index: TwoWay.pm =================================================================== RCS file: /cvsroot/poe/poe/POE/Pipe/TwoWay.pm,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** TwoWay.pm 14 Jul 2003 14:41:02 -0000 1.13 --- TwoWay.pm 16 Jul 2003 17:00:25 -0000 1.14 *************** *** 18,47 **** sub DEBUG () { 0 } - sub RUNNING_IN_HELL () { $^O eq 'MSWin32' or $^O eq 'MacOS' } - - # CygWin seems to have a problem with socketpair() and exec(). When - # an exec'd process closes, any data on sockets created with - # socketpair() is not flushed. From irc.rhizomatic.net #poe: - # - # <dngnand> Sounds like a lapse in cygwin's exec implementation. It - # works ok under Unix-ish systems? - # <jdeluise2> yes, it works perfectly - # <jdeluise2> but, if we just use poe::Pipe::TwoWay->new("pipe") it - # always works fine on cygwin - # <jdeluise2> by the way, it looks like the reason is that - # poe::Pipe::OneWay works because it tries to make a pipe - # first instead of a socketpair - # <jdeluise2> this socketpair problem seems like a long-standing one - # with cygwin, according to searches on google, but never - # been fixed. - # - # The problem occurred in POE::Wheel::Run, and that's where the - # solution was coded. If this becomes a general problem, we should - # force pipe() and INET sockets to be more important than socketpair() - # on that platform. - - # This flag is set true/false after the first attempt at using plain - # INET sockets as pipes. - my $can_run_socket = undef; sub new { --- 18,21 ---- *************** *** 58,70 **** my $b_write = gensym(); ! # Try UNIX-domain socketpair if no preferred conduit type is ! # specified, or if the specified conduit type is 'socketpair'. ! if ( (not RUNNING_IN_HELL) and ! ( (not defined $conduit_type) or ! ($conduit_type eq 'socketpair') ! ) and ! ( not defined $can_run_socket ) ! ) { eval { socketpair($a_read, $b_read, AF_UNIX, SOCK_STREAM, PF_UNSPEC) --- 32,60 ---- my $b_write = gensym(); ! if (defined $conduit_type) { ! ($a_read, $a_write, $b_read, $b_write) = ! $self->_try_type($conduit_type, $a_read, $a_write, $b_read, $b_write); ! return ($a_read, $a_write, $b_read, $b_write) if $a_read; ! } ! ! while (my $try_type = $self->get_next_preference()) { ! ($a_read, $a_write, $b_read, $b_write) = ! $self->_try_type($try_type, $a_read, $a_write, $b_read, $b_write); ! return ($a_read, $a_write, $b_read, $b_write) if $a_read; ! $self->shift_preference(); ! } + # There's nothing left to try. + DEBUG and warn "nothing worked"; + return (undef, undef, undef, undef); + } + + # Try a pipe by type. + + sub _try_type { + my ($self, $type, $a_read, $a_write, $b_read, $b_write) = @_; + + # Try a socketpair(). + if ($type eq "socketpair") { eval { socketpair($a_read, $b_read, AF_UNIX, SOCK_STREAM, PF_UNSPEC) *************** *** 72,106 **** }; ! # Socketpair succeeded. ! unless (length $@) { ! DEBUG and do { ! warn "using UNIX domain socketpairs"; ! warn "ar($a_read) aw($a_write) br($b_read) bw($b_write)\n"; ! }; ! # It's two-way, so each reader is also a writer. ! $a_write = $a_read; ! $b_write = $b_read; ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($a_write), $| = 1)[0]); ! select((select($b_write), $| = 1)[0]); ! return($a_read, $a_write, $b_read, $b_write); ! } ! elsif (DEBUG) { ! warn "socketpair failed: $@"; ! } ! } ! # Try the pipe if no preferred conduit type is specified, or if the ! # specified conduit type is 'pipe'. ! if ( (not RUNNING_IN_HELL) and ! ( (not defined $conduit_type) or ! ($conduit_type eq 'pipe') ! ) and ! ( not defined $can_run_socket ) ! ) { eval { pipe($a_read, $b_write) or die "pipe 1 failed: $!"; --- 62,89 ---- }; ! # Socketpair failed. ! if (length $@) { ! warn "socketpair failed: $@" if DEBUG; ! return (undef, undef, undef, undef); ! } ! DEBUG and do { ! warn "using UNIX domain socketpairs"; ! warn "ar($a_read) aw($a_write) br($b_read) bw($b_write)\n"; ! }; ! # It's two-way, so each reader is also a writer. ! $a_write = $a_read; ! $b_write = $b_read; ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($a_write), $| = 1)[0]); ! select((select($b_write), $| = 1)[0]); ! return ($a_read, $a_write, $b_read, $b_write); ! } + # Try a couple pipe() calls. + if ($type eq "pipe") { eval { pipe($a_read, $b_write) or die "pipe 1 failed: $!"; *************** *** 108,175 **** }; ! # Pipe succeeded. ! unless (length $@) { ! DEBUG and do { ! warn "using a pipe"; ! warn "ar($a_read) aw($a_write) br($b_read) bw($b_write)\n"; ! }; ! ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($a_write), $| = 1)[0]); ! select((select($b_write), $| = 1)[0]); ! return($a_read, $a_write, $b_read, $b_write); ! } ! elsif (DEBUG) { ! warn "pipe failed: $@"; } - } ! # Try a pair of plain INET sockets if no preffered conduit type is ! # specified, or if the specified conduit type is 'inet'. ! if ( ( RUNNING_IN_HELL or ! (not defined $conduit_type) or ! ($conduit_type eq 'inet') ! ) and ! ( $can_run_socket or (not defined $can_run_socket) ) ! ) { ! # Try using a pair of plain INET domain sockets. eval { ($a_read, $b_read) = $self->make_socket(); }; ! # Sockets worked. ! unless (length $@) { ! # Try sockets more often. ! $can_run_socket = 1; ! ! $a_write = $a_read; ! $b_write = $b_read; ! ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($a_write), $| = 1)[0]); ! select((select($b_write), $| = 1)[0]); ! DEBUG and do { ! warn "using a plain INET socket"; ! warn "ar($a_read) aw($a_write) br($b_read) bw($b_write)\n"; ! }; ! return($a_read, $a_write, $b_read, $b_write); ! } ! # Sockets failed. Don't try them again. ! else { ! DEBUG and warn "make_socket failed: $@"; ! $can_run_socket = 0; ! } } ! # There's nothing left to try. ! DEBUG and warn "nothing worked"; ! return(undef, undef, undef, undef); } --- 91,141 ---- }; ! # Pipe failed. ! if (length $@) { ! warn "pipe failed: $@" if DEBUG; ! return (undef, undef, undef, undef); } ! DEBUG and do { ! warn "using a pipe"; ! warn "ar($a_read) aw($a_write) br($b_read) bw($b_write)\n"; ! }; ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($a_write), $| = 1)[0]); ! select((select($b_write), $| = 1)[0]); ! return ($a_read, $a_write, $b_read, $b_write); ! } + # Try a pair of plain INET sockets. + if ($type eq "inet") { eval { ($a_read, $b_read) = $self->make_socket(); }; ! # Sockets failed. ! if (length $@) { ! warn "make_socket failed: $@" if DEBUG; ! return (undef, undef, undef, undef); ! } ! DEBUG and do { ! warn "using a plain INET socket"; ! warn "ar($a_read) aw($a_write) br($b_read) bw($b_write)\n"; ! }; ! $a_write = $a_read; ! $b_write = $b_read; ! # Turn off buffering. POE::Kernel does this for us, but someone ! # might want to use the pipe class elsewhere. ! select((select($a_write), $| = 1)[0]); ! select((select($b_write), $| = 1)[0]); ! return ($a_read, $a_write, $b_read, $b_write); } ! DEBUG and warn "unknown OneWay socket type ``$type''"; ! return; } |