Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Problems forking and redirecting STDOUT with Win32

by xdg (Monsignor)
on Dec 07, 2005 at 16:11 UTC ( [id://514879]=perlquestion: print w/replies, xml ) Need Help??

xdg has asked for the wisdom of the Perl Monks concerning the following question:

I've been trying to debug some test failures on IPC::Run3 on Win32. One of the tests evaluates how IPC::Run3 performs when called from a child process (which, of course, is really a thread on Win32). I'm seeing some very unusual results in how file descriptors get duplicated from within a child process. On investigation, I think it may be related to this perlbug. which has been sitting idle for a long time.

As an illustration of the issue, I took an example from the end of that bug report:

use strict; use warnings; if (my $pid=fork() ) { sleep(1); print "parent\n"; } else { open (STDOUT, ">test.txt"); system("echo child"); }

When I run this under Linux, "child" is written to test.txt and "parent" is printed to the console. However, when run under Win32 (Activestate 5.8.7 Build 815), both "child" and "parent" are written to test.txt and nothing is printed to the console.

Out of curiousity, I tried closing STDOUT before re-opening it, like this:

use strict; use warnings; if (my $pid=fork() ) { sleep(1); print "parent\n"; } else { close STDOUT; open (STDOUT, ">test.txt"); system("echo child"); }

Again, on Linux, "parent" goes to the console and "child" to test.txt. On Win32, though, the behavior reverses. "child" and "parent" are printed to the console and nothing is written to test.txt. (Side note: test.txt is still truncated).

I'm interested in any suggestions or alternatives for how to make this work consistently and portably.

Thanks!

Update: To clarify the solution I'm seeking -- it's not an alternative for the fork. I'm aware that there are probably better alternatives on Win32. The question is (I think): given that a fork has been done, is there a way of redirectly STDOUT safely in a way that doesn't also affect the parent so that system gets the right filehandle? If this can't be done, then IPC::Run3 will probably just need to skip the fork tests on Win32.

-xdg

Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Replies are listed 'Best First'.
Re: Problems forking and redirecting STDOUT with Win32
by secret (Beadle) on Dec 07, 2005 at 16:36 UTC
    Here is what Dave Roth says in his book "Win 32 perl programming" (new riders, http://books.perl.org/book/126 ) :

    Process can inherit Win32 handles. Notice that i am specifying Win32 handles, not Perl file handles; this is very important. (...) If the new process you create is a Perl script, however, don't expect to be able to access those opened sockets and files you inherited. This is because a Perl file handle differs from a Win32 handle. You see, Perl creates a file handle by asking the C language's runtime library to open the file. The C library, in turn, asks the operating system to open it. The Win32 API will return a handle (...) , and the C library will store the handle into some data structure it creates. A pointer to this structure will be returned to Perl, which puts this pointer into yet another structure. Perl will then associate a Perl file handle (...) with this structure. Because a new process does not have access to memory in other process, any inherited memory pointer won't point to the original memory structure.

    This means (as he concludes soon after) that only the Win32 file handle is inherited and not the Perl file handle.

    He suggests to use Win32::AdminMisc::GetStdHandle but the book is a bit outdated and my option is to use Win32::Job which allows to pass handles around.

    HTH,
    secret .

Re: Problems forking and redirecting STDOUT with Win32
by ikegami (Patriarch) on Dec 07, 2005 at 16:26 UTC
    Core modules IPC::Open2 and IPC::Open3 use the undocumented system 1, ... to spawn a child process in Windows. Dunno if that helps.
      undocumented system 1

      It's documented briefly in perlport in the alphabetical listing of Perl functions. In my quick test, it didn't seem to help. I should probably try the example I gave with IPC::Open2/3 and see what happens.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Problems forking and redirecting STDOUT with Win32 (skip)
by tye (Sage) on Dec 07, 2005 at 19:57 UTC

    You either need to not use fork or need to skip the test on Win32. Threads don't get an individual STDOUT.

    - tye        

      Is that limitation documented somewhere? The perlfork docs seems to imply that they do can be separate.

      Open handles to files, directories and network sockets All open handles are dup()-ed in pseudo-processes, so that closing any handles in one process does not affect the othe +rs. See below for some limitations.

      Here's the caveat that follows.

      Open filehandles Any filehandles open at the time of the fork() will be dup( +)-ed. Thus, the files can be closed independently in the parent a +nd child, but beware that the dup()-ed handles will still shar +e the same seek pointer. Changing the seek position in the parent + will change it in the child and vice-versa. One can avoid this b +y opening files that need distinct seek pointers separately i +n the child.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

        Kind of, yes, in the same document its written
        In the eyes of the operating system, pseudo-processes created via the fork() emulation are simply threads in the same process. This means that any process-level limits imposed by the operating system apply to all pseudo-processes taken together. This includes any limits imposed by the operating system on the number of open file, directory and socket handles, limits on disk space usage, limits on memory size, limits on CPU utilization etc.
        According to Win32 operating system, all threads share the same STDIN/STDOUT/STDERR, so in turn, all perl pseudo-processes (win32 os threads) share the same STDIN/STDOUT/STDERR, even if the perl globs (*STDIN/*STDOUT/*STDERR) are dup()ed, the underlying win32 filehandles remain the same.

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Problems forking and redirecting STDOUT with Win32
by PodMaster (Abbot) on Dec 08, 2005 at 10:27 UTC
    Update: To clarify the solution I'm seeking -- it's not an alternative for the fork. I'm aware that there are probably better alternatives on Win32. The question is (I think): given that a fork has been done, is there a way of redirectly STDOUT safely in a way that doesn't also affect the parent so that system gets the right filehandle? If this can't be done, then IPC::Run3 will probably just need to skip the fork tests on Win32.
    It can't be done, since perl just calls the win32 c runtime system

    Demo

    C:\>more perl.stdout.fork.pl use strict; use warnings; if (my $pid=fork() ) { sleep(1); print "parent\n"; } else { close STDOUT; open STDOUT, '>'. __FILE__.'.temp' or die $!; print "print child$/"; system("echo echo child"); # printed to console, not to .temp } C:\>perl perl.stdout.fork.pl echo child parent C:\>more perl.stdout.fork.pl.temp print child

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://514879]
Approved by holli
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2024-04-19 03:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found