On Wed Nov 11 02:42:31 2009, tjc wrote:
> Hi,
> could you please re-test this bug on the current version of Perl, 5.10.1, 
> and report back if the behaviour has been fixed.
> 
> Thanks.

Using Perl 5.17.6, this is still a problem, I guess, I didn't run 5.6 to
see what happens. Anyways

"    open(STDOUT,'>',$fn) or die "cannot open parent : $!";"

makes a call to CRT's dup2, fh 3 is the handle to fork_test.txt. fh 1 is
stdout. 

The line that calls PerlLIODup2 is

http://perl5.git.perl.org/perl.git/blob/93a641ae382638ffd1:/doio.c#l617

____________________________________________________________
        msvcr71.dll!_dup2(int fh1=3, int fh2=1)  Line 57        C
        perl517.dll!PerlLIODup2(IPerlLIO * piPerl=0x00344364, int handle1=3,
int handle2=1)  Line 959 + 0xd  C
>       perl517.dll!Perl_do_openn(interpreter * my_perl=0x00345ecc, gv *
gv=0x008fd034, const char * oname=0x00b41414, long len=1, int as_raw=0,
int rawmode=0, int rawperm=0, _PerlIO * * supplied_fp=0x00000000, sv * *
svp=0x00a7b020, long num_svs=1)  Line 617 + 0x1e        C
        perl517.dll!Perl_pp_open(interpreter * my_perl=0x00345ecc)  Line 638
+ 0x2e  C
        perl517.dll!Perl_runops_standard(interpreter * my_perl=0x00345ecc) 
Line 42 + 0xa   C
        perl517.dll!S_run_body(interpreter * my_perl=0x00345ecc, long
oldscope=1)  Line 2430 + 0xd    C
        perl517.dll!perl_run(interpreter * my_perl=0x00345ecc)  Line 2349       
C
        perl517.dll!RunPerl(int argc=2, char * * argv=0x00342478, char * *
env=0x003451f0)  Line 270 + 0x9 C
        perl.exe!mainCRTStartup()  Line 398 + 0xe       C
        kernel32.dll!_BaseProcessStart@4()  + 0x23      
___________________________________________________________________
Then CRT dup2 winds up calling
"                    SetStdHandle( STD_OUTPUT_HANDLE, (HANDLE)value );",
which is per Win32 process, with callstack,
______________________________________________________________________
>       kernel32.dll!_SetStdHandle@8()  
        msvcr71.dll!_dup2(int fh1=3, int fh2=1)  Line 98 + 0x7  C
        perl517.dll!win32_dup2(int fd1=3, int fd2=1)  Line 3293 + 0xe   C
        perl517.dll!PerlLIODup2(IPerlLIO * piPerl=0x00344364, int handle1=3,
int handle2=1)  Line 959 + 0xd  C
        perl517.dll!Perl_do_openn(interpreter * my_perl=0x00345ecc, gv *
gv=0x008fd034, const char * oname=0x00becc34, long len=1, int as_raw=0,
int rawmode=0, int rawperm=0, _PerlIO * * supplied_fp=0x00000000, sv * *
svp=0x00a7aff8, long num_svs=1)  Line 617 + 0x1e        C
        perl517.dll!Perl_pp_open(interpreter * my_perl=0x00345ecc)  Line 638
+ 0x2e  C
        perl517.dll!Perl_runops_standard(interpreter * my_perl=0x00345ecc) 
Line 42 + 0xa   C
        perl517.dll!S_run_body(interpreter * my_perl=0x00345ecc, long
oldscope=1)  Line 2430 + 0xd    C
        perl517.dll!perl_run(interpreter * my_perl=0x00345ecc)  Line 2349       
C
        perl517.dll!RunPerl(int argc=2, char * * argv=0x00342478, char * *
env=0x003451f0)  Line 270 + 0x9 C
        perl.exe!mainCRTStartup()  Line 398 + 0xe       C
        kernel32.dll!_BaseProcessStart@4()  + 0x23      
______________________________________________________________________

The test script I am using is
___________________________________________________________________

#!/usr/bin/perl -w
use Data::Dumper;
use warnings;
use strict;
use Win32API::File 'FdGetOsFHandle';

`del fork_test.txt`;
my $fn = 'fork_test.txt';
my $pid;
warn "b4 fork STDOUT ".sprintf("%x", FdGetOsFHandle(fileno(STDOUT)))."\n";
if ($pid = fork)
{
    print "Hello from ithread 1\n";
    #sleep 1;
    warn "p b4 STDOUT ".sprintf("%x", FdGetOsFHandle(fileno(STDOUT)))."\n";
    sleep 5;
    open(STDOUT,'>',$fn) or die "cannot open parent : $!";
    warn "p aftr STDOUT ".sprintf("%x",
FdGetOsFHandle(fileno(STDOUT)))."\n";
    system('ipconfig');
    close STDOUT;
    waitpid($pid,0);
}
else
{
    die 'Couldn\'t fork!' unless defined $pid;
    #sleep 2;
    warn "c1 STDOUT ".sprintf("%x", FdGetOsFHandle(fileno(STDOUT)))."\n";
    warn "c1 READ ".sprintf("%x", FdGetOsFHandle(fileno(READ)))."\n";
    open(READ,'<',$fn)  or die "cannot open parent : $!";
    warn "c2 READ ".sprintf("%x", FdGetOsFHandle(fileno(READ)))."\n";
    print "Hello from ithread 2\n";
    my $l;
    do
    {
        undef $l; my $i = 0;
        while(!defined($l))
        {
            my $slp = int(($i++ + 9) / 10);
            sleep($slp);
            $l = <READ>;
        };
    print $l;
    } until($l =~ /Gateway/);
    close READ;
    sleep 10000;
}
____________________________________________________________
How to fix this, I guess all fileno calls need to be hooked, with a per
perl interp set of Perl level FDs that are then converted to CRT level
FDs. On a clone/fork, all the FDs of the parent interp are duped to new
CRT level FDs, but the Perl level FDs stay the same. Not sure where and
how the hooking should happen. No idea if this will work, but its beyond
my skill set. Comments?

I wonder if this bug can be done with ithreads.
-- 
bulk88 ~ bulk88 at hotmail.com

---
via perlbug:  queue: perl5 status: open
https://rt.perl.org:443/rt3/Ticket/Display.html?id=22948

Reply via email to