problem with forks writing to files on XP

F

Franklin H.

As a test case for forking and having each fork write to a file I did
the following:

### begin foo.pl:
#!perl

use strict;
my $trials = 2;
foreach my $i (1 .. $trials) {
unless (fork) {
# child
my $outfile = "${i}.txt";
my $cmd = "perl bar.pl $i |";
open (CMD, $cmd) or die $!;
open (FILE, ">$outfile") or die $!;
while (<CMD>) {
print FILE $_;
}
warn "$i cmd finished\n";
close FILE;
close CMD;
exit;
}
}
exit;
#### end foo.pl

### begin bar.pl:
#!perl

print "$ARGV[0]\n";
close STDOUT;
warn "*** $ARGV[0] program completed\n";
exit;
### end bar.pl

The stderr I'm getting is:
*** 1 program completed
*** 2 program completed
*** 3 program completed
3 cmd finished
1 cmd finished

but I'm never seeing one of the processes actally complete in the
cakker script (foo.pl). This occurs for any value of $trials > 1.

Any idea what the heck could be wrong?
 
F

Franklin H.

I should probably also point out that this problem occurs undere XP but
not under LINUX.
 
A

Anno Siegel

Franklin H. said:
As a test case for forking and having each fork write to a file I did
the following:

### begin foo.pl:
#!perl

use strict;
my $trials = 2;
foreach my $i (1 .. $trials) {
unless (fork) {
# child

Nope. In the parent fork returns true, the kid can find its own PID.
So your code (not looked at) runs under wrong assumptions.

Anno
 
F

Franklin H.

Franklin H. said:
As a test case for forking and having each fork write to a file I did
the following:
### begin foo.pl:
#!perl
use strict;
my $trials = 2;
foreach my $i (1 .. $trials) {
unless (fork) {
# child

Anno Siegel replied:
Nope. In the parent fork returns true, the kid can find its own PID.
So your code (not looked at) runs under wrong assumptions.

I do apologize, Anno, but I don't understand what you're saying here.

I did write
unless (fork) { # child }

not

if (fork) { # child }

or am I missing something?
 
X

xhoster

Franklin H. said:
As a test case for forking and having each fork write to a file I did
the following:

### begin foo.pl:
#!perl

use strict;
my $trials = 2;
foreach my $i (1 .. $trials) {
unless (fork) {

Maybe a fork is failing for some reason. You should make sure it
not undefined, and die $! if it is.
# child
my $outfile = "${i}.txt";
my $cmd = "perl bar.pl $i |";
open (CMD, $cmd) or die $!;

When debugging, I would surely not do this until after I showed that a
simpler version (which simply printed to the file without doing another
implicit fork) worked first.
open (FILE, ">$outfile") or die $!;
while (<CMD>) {
print FILE $_;
}
warn "$i cmd finished\n";
close FILE;
close CMD;
exit;
}
}
exit;

You should probably wait for all the children to exit before the parent
exits. Probably the parent doesn't see the child exit because the parent
itself is already gone.

Xho
 
G

Gunnar Hjalmarsson

Maybe a fork is failing for some reason. You should make sure it
not undefined, and die $! if it is.



When debugging, I would surely not do this until after I showed that a
simpler version (which simply printed to the file without doing another
implicit fork) worked first.


You should probably wait for all the children to exit before the parent
exits. Probably the parent doesn't see the child exit because the parent
itself is already gone.

All that is conveniently taken care of by Parallel::ForkManager. ;-)
 
F

Franklin H.

Maybe a fork is failing for some reason. You should make sure it
not undefined, and die $! if it is.
Good point. But I did try this and none of the forks are failing.
When debugging, I would surely not do this until after I showed that a
simpler version (which simply printed to the file without doing another
implicit fork) worked first.
Another good point. But I did try it and it did work.
You should probably wait for all the children to exit before the parent
exits. Probably the parent doesn't see the child exit because the parent
itself is already gone.
If I'm not mistaken the ActiveState version of perl will not allow the
parent to exit until all child processes have completed, thereby making
a wait in this context superfluous, no?

I think this is actually just some weird STDOUT issue under XP. For
some reason the caller program (foo.pl) never sees the final EOF. When
I change bar.pl to:

#!perl

print "$ARGV[0]\n";
print "\017\n"; # added this line
close STDOUT;
warn "*** $ARGV[0] program completed\n";
exit 0;


## end

and change foo.pl to read:
#!perl

use strict;
my $trials = 3;
my ($pid,);
foreach my $i (1 .. $trials) {
unless ($pid = fork) {
die $! unless defined $pid;
# child
my $outfile = "${i}.txt";
my $cmd = "perl bar.pl $i |";
open (CMD, $cmd) or die $!;
open (FILE, ">$outfile") or die $!;
while (<CMD>) {
if (m/\017/) { # added this
close FILE; # added this
close CMD; # added this
last; # added this
} # added this
print STDERR $_;
print FILE $_;
}
warn "$i cmd finished\n";
close FILE;
close CMD;
exit;
}
}
exit;



# END


then everything works fine. My guess is that this is just some
XP/Active State bug ...
 
X

xhoster

Gunnar Hjalmarsson said:
All that is conveniently taken care of by Parallel::ForkManager. ;-)

Yes, I fully support use of Parallel::ForkManager once one has already
decided you don't need to capture the output! I've been wanting to extend
ForkManager to include report back (or fuse Parallel::ForkManager and
Parallel::Jobs together) for a while, but haven't gotten around to it.
Mostly because I would have a hard time testing my work for portability off
of linux.

Xho
 
A

Anno Siegel

Franklin H. said:
Anno Siegel replied:


I do apologize, Anno, but I don't understand what you're saying here.

You are right. One boolean twist too many. Apologies.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,466
Latest member
DrusillaYa

Latest Threads

Top