Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Win32 fork() "problem"

by maa (Pilgrim)
on Mar 26, 2004 at 11:03 UTC ( [id://339977]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I'm clearly doing something stupid but I can't see what it is. I've broken the test code down to a small case that exhibits the odd behaviour. Can anyone see/explain what I'm doing wrong here? (Apart from using fork() on winnt at all, that is.)

#!C:/Activeperl/bin/perl.exe use strict; use warnings; open (IN, "fork2.ini") or die("Can't open input file $!\n"); my $pid=0; my $x=0; while (my $computer=<IN>) { chomp($computer); $x++; $pid = fork(); if ($pid) { print STDERR "Parent $$ got PID $pid from fork($$ $computer)\n +"; sleep(1); }else { print STDERR "\t$$ $computer\n"; exit(0); } if($x > 4) { do { $pid=wait() } while ($pid != -1); $x=0; } } do { $pid=wait() } while ($pid != -1); print "wait() ed until $pid was returned.\n"; close(IN); __DATA__ Computer1 Computer2 Computer3

The file "fork2.ini" contains the asme as the __DATA__ part... another weirdness is that if I don't use <IN> and use <DATA> instead it prints out the source code!

The output I get from running this is:

C:\logchecks>fork3
Parent 433 got PID -605 from fork(433 test1)
        -605 test1
Parent 433 got PID -461 from fork(433 test2)
        -461 test2
Parent 433 got PID -533 from fork(433 test3)
        -533 test3
Parent 433 got PID -105 from fork(433 test2)
        -105 test2
Parent 433 got PID -521 from fork(433 test3)
        -521 test3
Parent 433 got PID -670 from fork(433 test3)
        -670 test3
wait() ed until -1 was returned.
Done

As you can see, it's printing values from the files out more than once. (Which I don't think it should.)

Seeking enlightenment... Mark.

UPDATE: if I change a couple of things it works...

my (@Computers=(<IN>); #Do this #while (my $computer=<IN>) { #change this while (my $computer=pop @Computers) { #to this

I still don't understand what was going wrong in the original, however.

Replies are listed 'Best First'.
Re: Win32 fork() "problem"
by dawn (Novice) on Mar 26, 2004 at 11:49 UTC
    I've never used them, but a perl book I read recently suggests Win32::Spawn or Win32::Process modules if Fork is being difficult (Fork is introduced experimentally on Win32 systems in Perl 5.6.1). The latter is more robust, more advanced but harder.

      Hi, dawn

      I've looked at those modules already and will probably end up utilising Win32::Job on an XP box at some point. This has the benefit of easily being able to set a timeout for a command using $job->run($cmd,$timeout) which is a huge improvement for Win32 platforms.

      I was really hoping I had made a glaring logic error (rather than fork() just playing up) in my use of fork...

      If I can't get a simple case like this to work (does this work on another platform?) I'll have to resort to a more brute force method of divvying up work. :-(

        FYI, your code works fine on Linux. Here is the output:
        Parent 962 got PID 963 from fork(962 Computer1) 963 Computer1 +Parent 962 got PID 964 from fork(962 Computer2) 964 Computer2 + 965 Computer3 Parent 962 got PID 965 from fork(962 Computer3) +Parent 962 got PID 966 from fork(962 ) 966 +wait() ed until -1 was returned.
        Another module that you might look into is IPC::Run. I know that it has at least some Win32 functionality.
Re: Win32 fork() "problem"
by runrig (Abbot) on Mar 27, 2004 at 09:33 UTC
    I get similar behavior on Win2000. The fork appears to mess with the file handle:
    #!/usr/bin/perl use strict; use warnings; my $x=0; while (my $computer=<DATA>) { print "computer: [$computer]"; chomp($computer); $x++; my $pid = fork(); if ($pid) { print "Parent $$ got PID $pid from fork($$ $computer)\n"; sleep(1); }else { print "\t$$ $computer\n"; exit(0); } if($x > 4) { do { $pid=wait() } while ($pid != -1); $x=0; } } my $pid; do { $pid=wait() } while ($pid != -1); print "wait() ed until $pid was returned.\n"; close(DATA); __DATA__ Computer1 Computer2 Computer3 # Output computer: [Computer1 ]Parent 1782987 got PID -1853375 from fork(1782987 Computer1) -1853375 Computer1 computer: [ ]Parent 1782987 got PID -1852747 from fork(1782987 ) -1852747 computer: [Computer2 ]Parent 1782987 got PID -1805143 from fork(1782987 Computer2) -1805143 Computer2 computer: [ ]Parent 1782987 got PID -1804643 from fork(1782987 ) -1804643 computer: [Computer3 ]Parent 1782987 got PID -1898099 from fork(1782987 Computer3) -1898099 Computer3 wait() ed until -1 was returned.
    The problem goes away if you slurp the input first, like:
    for my $computer (<DATA>) { ...
Re: Win32 fork() "problem"
by terris (Initiate) on Mar 28, 2004 at 16:14 UTC
    You're lucky. In my script, fork() causes perl.exe to exhibit bizarre behavior and crash. ActivePerl 809.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2024-03-28 08:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found