fork and pipe - problem prone

T

theater

Hello,

When you fork() you'd like your child to be able to communicate with the
father, and vice versa. This has usually been handled with the help of
pipe() and this is also usually prone to troubles...
Such as this one:

I only want to kid to talk to daddy, not the other way round.
I create the pipe.
Then I have a loop , each iteration will create a new child.
Here's a snippet: (lots of error checking omitted here for the sake of
simplicity)

pipe(READHANDLE, WRITEHANDLE);
foreach $myKid ( @childrenList ) {
$pid = fork();
if($pid == 0) {
# I am the kid
# I close the reading end of the pipe
close(READHANDLE);
# and then I do y stuff and exit
exit;
}
else {
# I am the father, yes i know i should check for error, # but this
is just an example
# i do my stuff here
}
}

--> the problem is:
1/ if i leave it like above, some of the kids will be stuck... They just
don't exit(). It's not a resource problem because in reality i control
the number of simultaneous children.
And I have a print() statement just before exit()ing and I can see it
when debugging.
First of all I'm clueless about why this happens, but...

2/ if I close() the WRITEHANDLE end of the pipe in the father's section,
then I have absolutely no deadlock problem anymore BUT I won't be able
to get the other children to write anymore as they inherit from the
father, and after the 1st child this handle will be closed...


This seems to be quite common but in the case of a loop I have not seen
any solutions / fix.

Thanks for sharing your thoughts on this matter.
 
X

xhoster

theater said:
Hello,

When you fork() you'd like your child to be able to communicate with the
father, and vice versa. This has usually been handled with the help of
pipe() and this is also usually prone to troubles...
Such as this one:

I only want to kid to talk to daddy, not the other way round.
I create the pipe.
Then I have a loop , each iteration will create a new child.
Here's a snippet: (lots of error checking omitted here for the sake of
simplicity)

As Einstein may have said, "Make everything as simple as possible, *but not
simpler*."
pipe(READHANDLE, WRITEHANDLE);

You should probably use lexical file filehandles.
foreach $myKid ( @childrenList ) {
$pid = fork();
if($pid == 0) {
# I am the kid
# I close the reading end of the pipe
close(READHANDLE);
# and then I do y stuff and exit
exit;
}
else {
# I am the father, yes i know i should check for error,
# but this is just an example
# i do my stuff here
}
}

--> the problem is:
1/ if i leave it like above, some of the kids will be stuck... They just
don't exit().

Your example code does not exhibit this problem. That makes it nearly
useless as an example.

It's not a resource problem because in reality i control
the number of simultaneous children.
And I have a print() statement just before exit()ing and I can see it
when debugging.

Do you know that the child that you see invoking the print is the same
child that "hangs"?
First of all I'm clueless about why this happens, but...

2/ if I close() the WRITEHANDLE end of the pipe in the father's section,

Inside the loop or after the loop?
then I have absolutely no deadlock problem anymore BUT I won't be able
to get the other children to write anymore as they inherit from the
father, and after the 1st child this handle will be closed...

This seems to be quite common but in the case of a loop I have not seen
any solutions / fix.

Without seeing any examples of how you actually use the filehandles, it is
hard to say.

Xho
 
U

Uri Guttman

t> I only want to kid to talk to daddy, not the other way round. I
t> create the pipe. Then I have a loop , each iteration will create a
t> new child. Here's a snippet: (lots of error checking omitted here
t> for the sake of simplicity)

t> pipe(READHANDLE, WRITEHANDLE);

that pair of handles is the same in the parent and all the children. you
need a fresh pipe with fresh handles for each child. allocate handles
with IO::Handle or Symbol::gensym. or use a module (many to choose from)
that does this for you.

t> foreach $myKid ( @childrenList ) {
t> $pid = fork();
t> if($pid == 0) {
t> # I am the kid
t> # I close the reading end of the pipe
t> close(READHANDLE);
t> # and then I do y stuff and exit

and if the handle is closed by another child, it will never do
anything. hang.

and i suspect many other problems as well since managing forked children
and pipes isn't as simple as you think it is. again, use a module
designed to do this for you.

uri
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top