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

Ok, I am playing around with forks and pipes and am trying to write from the parent process to a child process (created with Proc::Fork, which i adore), but the child will read from the pipe until it recieves and EOF. The only way I know to do this to send this is to close the pipe. In the rather terrible example below this lack of knowledge is fatal.

use Proc::Fork; use IO::Pipe; my ($pipe) = new IO::Pipe; child { $pipe->reader(); while (1) { while ($num = <$pipe>) { } print "Child: $num\n" if $old_num != $num; $old_num = $num; last if $num == 644; } exit; }; $pipe->writer(); while (1) { $in = <>; chomp $in; print $pipe $in; last if $in == 644; }

This outputs all the things I have sent over pipe together. It wont break them apart. When I enter 644 the parent dies (closing the pipe), and the child prints the string of numbers it recieved and then just goes on without a care in the world. I have tried putting lasts in the child while loop (ie.

While ($num = <$pipe>) {
    last;
}
and that doesn't work. Any ideas are more then welcome. For the record i have super searched and perldoc'ed IO::Pipe. Cant find the answer anywhere. I know if you use IO::Handle you can do something like $pipe->eof;, but know how to integrate IO::Pipe and IO::Handle.

INPUT:
5
62
345
23
644

OUTPUT:
Child: 56234523644

Desired OUTPUT:
Child: 5
Child: 62
Child: 345
Child: 23
Child: 644

Replies are listed 'Best First'.
Re: Sending EOF to pipe
by Zaxo (Archbishop) on Jul 03, 2002 at 04:16 UTC

    You have a couple of things here which are interacting to give you your unexpected result. I've added a few more comments which may make the code a little more robust.

    1. By chomping data input in the parent, you remove the input record seperator, $/.
    2. The child does not process any but the last record. The inner while loop is empty. This behavior is masked by #1, you only have one record.
    3. You don't appear to have autoflush on for the pipe. That makes the child sit around till EOF or a full buffer condition.
    4. You should call exit in the child with argument 0. An irrelevent nitpick, but worth repairing.
    5. Both while (1) {} loops seem unnecessary.
    6. There's no need to test for the special '644' end line in the child, eof will take care of that.

    If you correct the first two, the code should work.

    After Compline,
    Zaxo

Re: Sending EOF to pipe
by rsteinke (Scribe) on Jul 03, 2002 at 03:25 UTC

    You need to stick some delimeters in your output. The code

    my ($num1,$num2) = (3, 24); print "$num1$num2\n";

    will output the number 324. You're doing something similar with your pipe. Sitck an endline in the print statement in parent,

    print $pipe "$in\n"

    so that the line-at-a-time read in the child works properly.

    Ron Steinke rsteinke@w-link.net
•Re: Sending EOF to pipe
by merlyn (Sage) on Jul 03, 2002 at 15:55 UTC
    With the triviality of setting up an HTTP daemon with HTTP::Daemon, and talking to it with HTTP::Request::Common, there's probably no reason to "invent" your own protocol. Eventually, you'll probably want parameter escaping, and length checking, and perhaps even encryption. Bing. All for free with HTTP.

    Please don't try to invent TCP protocols without first understanding why existing protocols aren't precisely what you need, and without studying prior art.

    -- Randal L. Schwartz, Perl hacker