children not getting eof from pipe


K

kspecial

i've got this issue in where i'm sending data to forked children and
yet they don't want to ever recieve eof() even after the parent closes
the write side. I've looked throughout the camel for any information I
might have missed, but honestly can't seem to locate what it might be.
Maybe if someone here takes a look they will either notice an error or
know a reason.

Code:
use strict;

my $forks = 5;
my (@fd, $num, $oldpid, @results, $read, $write);

for (; $num < $forks; $num++) {
my ($read, $write);
pipe($read, $write);
select((select($write), $|++)[0]);
$fd[$num][0] = $read;
$fd[$num][1] = $write;
}

$oldpid = $$;
for (undef($num); $num < $forks; $num++) {
$read = $fd[$num][0];
$write = $fd[$num][1];
if (fork) { close($read); } else { close($write); last; }
}

if ($oldpid == $$) {
for ($a = 0; $a < 100; $a++) { push (@results, $a) }
my $num = 0;

foreach my $result (@results) {
print { $fd[$num][1] } "$result" . "\n";
$num++;
$num = 0 if $num == $forks;
}
foreach (0..$forks) {
close($fd[$_][1]) or die "-!> error closing an fd\n";
}
}
else {
while(!(eof($read))) {
my $data = readline($read);
print "I'm child $$ with: $data";
}
exit(0);
}

linux, btw

appreciatively,
 
Ad

Advertisements

X

xhoster

i've got this issue in where i'm sending data to forked children and
yet they don't want to ever recieve eof() even after the parent closes
the write side. I've looked throughout the camel for any information I
might have missed, but honestly can't seem to locate what it might be.
Maybe if someone here takes a look they will either notice an error or
know a reason.

Code:
use strict;

my $forks = 5;
my (@fd, $num, $oldpid, @results, $read, $write);

for (; $num < $forks; $num++) {
my ($read, $write);
pipe($read, $write);
select((select($write), $|++)[0]);
$fd[$num][0] = $read;
$fd[$num][1] = $write;
}[/QUOTE]

You have pre-built all the filehandles.  Don't do that.  Not only is it
messay, it causes the problem you are inquiring about.
[QUOTE]
$oldpid = $$;
for (undef($num); $num < $forks; $num++) {
$read = $fd[$num][0];
$write = $fd[$num][1];
if (fork) { close($read); } else { close($write); last; }
}[/QUOTE]

Every child not has a copy of @fd, and therefore has open write
handles into every other child.

The eof condition is not met until *all* of those handles are closed.
Since the children never close their copies of the handles they hold to
other children, this never happens.

Xho
 
X

xhoster

i've got this issue in where i'm sending data to forked children and
yet they don't want to ever recieve eof() even after the parent closes
the write side. I've looked throughout the camel for any information I
might have missed, but honestly can't seem to locate what it might be.
Maybe if someone here takes a look they will either notice an error or
know a reason.

Code:
use strict;

my $forks = 5;
my (@fd, $num, $oldpid, @results, $read, $write);

for (; $num < $forks; $num++) {
my ($read, $write);
pipe($read, $write);
select((select($write), $|++)[0]);
$fd[$num][0] = $read;
$fd[$num][1] = $write;
}[/QUOTE]

You have pre-built all the filehandles.  Don't do that.  Not only is it
messy, it causes the problem you are inquiring about.
[QUOTE]
$oldpid = $$;
for (undef($num); $num < $forks; $num++) {
$read = $fd[$num][0];
$write = $fd[$num][1];
if (fork) { close($read); } else { close($write); last; }
}[/QUOTE]

Every child now has a copy of @fd, and therefore has open write
handles into every other child.

The eof condition is not met until *all* of those handles are closed.
Since the children never close their copies of the handles they hold to
other children, this never happens.

Xho
 
X

xhoster

Jim Gibson said:
$oldpid = $$;
for (undef($num); $num < $forks; $num++) {
$read = $fd[$num][0];
$write = $fd[$num][1];
if (fork) { close($read); } else { close($write); last; }
}
....
}
else {
while(!(eof($read))) {
my $data = readline($read);

The value of $read here is incorrect except for the last child. All
children are reading from the same pipe, the last one created.

It is hard to tell from the weird code, but it does look like each
child has a different $read at the time they "last" out of the for
loop.

Xho
 
K

kspecial

Xho your first post has helped me imensely. I appreciate it.

Jim, i don't understand why they would be reading from the wrong file
handle, in the fork creating loop the parent sets $read to that childs
file descriptor made above, ie if the loop was the second one, $read =
$fd[1][0], the child would inherit $read from the parent, and on the
3rd child creating loop $read = $fd[2][0] and the third child would
inherit $read into it's memory, and so on.

--K-sPecial
 
K

kspecial

btw, here is what I did to make it work, same thing realy, it just
fixes the problem xho mentioned in his first post:

1 use strict;
2
3 my $forks = 5;
4 my (@fd, $num, $oldpid, @results, $read, $write);
5
6 $oldpid = $$;
7 for (undef($num); $num < $forks; $num++) {
8 undef($read); undef($write);
9 pipe($read, $write);
10 select((select($write), $|++)[0]);
11 if (fork) { close($read); $fd[$num][1] = $write } else
{ close($write); last; }
12 }
13
14 if ($oldpid == $$) {
15 for ($a = 0; $a < 100; $a++) { push (@results, $a) }
16 my $num = 0;
17
18 foreach my $result (@results) {
19 print { $fd[$num][1] } "$result" . "\n";
20 $num++;
21 $num = 0 if $num == $forks;
22 }
23 foreach (0..$forks) {
24 close($fd[$_][1]) or die "-!> error closing an
fd\n";
25 }
26 }
27 else {
28 while (chomp(my $data = <$read>)) {
29 print "I'm child $$ with: $data\n";
30 }
31 exit(0);
32 }

[email protected]:~$ perl heh.pl
I'm child 4417 with: 0
I'm child 4418 with: 1
I'm child 4419 with: 2
I'm child 4420 with: 3
I'm child 4421 with: 4
I'm child 4417 with: 5
I'm child 4418 with: 6
I'm child 4419 with: 7
I'm child 4420 with: 8
I'm child 4421 with: 9
I'm child 4417 with: 10

I added a sleep (1) after the parent sends to an fd, just so things
happen a lil slower.

This post has been answered and and should be considered closed and
complete.

--K-sPecial
 
Ad

Advertisements

A

A. Sinan Unur

(e-mail address removed) wrote in @g47g2000cwa.googlegroups.com:
btw, here is what I did to make it work, same thing realy, it just
fixes the problem xho mentioned in his first post:

When posting a response, please respond to each post separately, and
give enough context so your post can stand on its own.
1 use strict;

Please code with line numbers. It makes it unnecessarily inconvenient to
run your code.

BTW, you are missing

use warnings;

3 my $forks = 5;
4 my (@fd, $num, $oldpid, @results, $read, $write);

All of the undef ugliness below, and potentially some of your problems,
can be avoided if you declared your variables in the smallest applicable
scope.
5
6 $oldpid = $$;
7 for (undef($num); $num < $forks; $num++) {
8 undef($read); undef($write);
9 pipe($read, $write);
10 select((select($write), $|++)[0]);
11 if (fork) { close($read); $fd[$num][1] = $write } else
{ close($write); last; }
12 }

If you are not trying to make your code hard to read on purpose, then I
think you really need to realize that you are indeed making your code
hard to read. Your interests would be best served by making your code
easier to read.

perldoc perlstyle

might be of help.

23 foreach (0..$forks) {
24 close($fd[$_][1]) or die "-!> error closing an
fd\n";

Your for loop above interates 5 times. This will iterate 6 times. There
won't be a valid file descriptor in $fd[5][1].
28 while (chomp(my $data = <$read>)) {

You seem to be confused about what chomp returns.

perldoc -f chomp/
I added a sleep (1) after the parent sends to an fd, just so things
happen a lil slower.

Don't sweep the bug under the rug, fix it.
This post has been answered and and should be considered closed and
complete.

I don't understand what you mean.

Sinan
 

Top