At 6:54 PM -0600 1/16/05, Craig A. Berry wrote:

> >With ActivePerl 810 (5.8.4) running under Win2000 and feeding it the
>>"pause" command, I get the same behaviour as under VMS, including the
>>results of "perl -V:useperlio". I have to hit return before the script
>>exits. Unlike 5.6.1, though, you _can_ use SIGALRM under Windows to time
>>out something like "sleep 1 until $timeout" (where $timeout is set by the
>>alarm handler). So we're closer, but still no cigar.
>>
>>Oddly enough, with Cygwin on the same machine as the ActivePerl 810 test
>>(Perl 5.8.6 this time) it works as advertised: 'sleep 30' with a 10-second
>>timeout completes in 10 seconds, using both :perlio and :stdio. I will
>>withhold the obvious editorial comment.
>>
>>I can check Darwin over the weekend, but after that I'll be pretty much
>>out of "various platforms" I can test personally.
>
>You've definitely proven it works differently on VMS.  So lets look
>at what's going on a bit deeper.  In mg.c, you can see in
>Perl_csighander and Perl_raise_signal what happens differently when
>unsafe signals are allowed and when they're not.  When they're not,
>it just sets a flag that basically means "check me later."  That
>check only happens when PERL_ASYNC_CHECK() is called, which is
>defined in perl.h like so:
>
># define PERL_ASYNC_CHECK() if (PL_sig_pending) despatch_signals()
>
>The reason you're getting blocked must have something to do with our
>pipe implementation, which, since it's doing mailbox reads and writes
>via $QIOs, knows nothing about the Perl I/O layers.  Those layers
>have PERL_ASYNC_CHECK() sprinkled all through them; whenever an I/O
>completes, it checks for pending signals.
>
>Fixing this may be as simple as putting PERL_ASYNC_CHECK() as the
>last line in each of the AST routines involved in pipe I/O in
>[.vms]vms.c.  Then again, who knows what mayhem might result from
>doing this at AST level. I guess we won't know until we try, so I
>will see if I can work up a patch and get back to you.

Well, of course it's not that simple.  What was I thinking? :-(  A
bit more analysis shows that where it gets stuck is in the parent,
which is not doing one of our pipe $QIOs at AST level, but is instead
sitting there in a plain old fgetc() waiting for the child to write
something to it.  The call stack looks like the following, where
PerlIOStdio_read is calling fgetc():

*PERLIO         PerlIOStdio_read
                                58337       0000000000006E2C 000000000047B9FC
*PERLIO         Perl_PerlIO_read
                                56901       00000000000033F8 0000000000477FC8
*PERLIO         PerlIO_getc     60112       000000000000A8D0 000000000047F4A0
*SV             Perl_sv_gets    57205       00000000000117E4 0000000000564A84
*PP_HOT         Perl_do_readline
                                50819       00000000000072F4 0000000000544AF4
*PP_HOT         Perl_pp_readline
                                49490       0000000000001534 000000000053ED34
*DUMP           Perl_runops_debug
                                51570       0000000000007004 00000000005130D4
*PERL           S_run_body      51183       000000000000444C 000000000046C87C
*PERL           perl_run        51112       0000000000004008 000000000046C438

PerlIOStdio_read will call PERL_ASYNC_CHECK() and process any pending
signals, but it will not do so until the fgetc() completes, and the
fgetc() will not complete unless the child actually sends it
something.  This can be demonstrated by running the following
procedure from Tom's test script:

$ type trw.com
$ i = 0
$ loop:
$   i = i + 1
$   wait 00:00:03
$   write sys$output "hello #''i'"
$   if i .gt. 10 then exit
$ goto loop
$ exit

$ perl trw.pl -timeout 5 @trw
hello #1
hello #2

     Command: '@trw'
      Access: '-|'
     Timeout: 5
Elapsed time: 6 seconds.
   Timed out? Yes

So the first time a read completes after a signal has fired, the
signal gets processed.  Clearly we can't put anything inside of
fgetc() to check for Perl's pending signals.  The only curiosity now
is what's happening on platforms where the parent is reading but the
child is not writing -- how are we checking for signals in that case?

-- 
________________________________________
Craig A. Berry
mailto:[EMAIL PROTECTED]

"... getting out of a sonnet is much more
 difficult than getting in."
                 Brad Leithauser

Reply via email to