in reply to Reading from a pipe

You have to close the writing end of the pipe in the parent. The fork duplicates the pipe's handles, and the readline (i.e. my @val = <READ>) doesn't stop reading until the pipe is fully closed (i.e. in both child and parent).

This should work:

... sub _Forked { my $ip = shift; pipe (READ,WRITE); die "Couldn't fork" unless defined (my $pid = fork()); if ($pid == 0) { # CHILD my @ping = `ping $ip -w 2 -q | sed -n '\$p'`; close (READ); select WRITE; print "@ping\n"; close (WRITE); # exit (0); } # close WRITE; # <--- return ($pid); } ...

Note that you have to move the creation of the pipe into the _Forked() routine (otherwise you'd have a dysfunctional pipe with a closed writing end upon subsequent calls of the routine...).

That said, I'm not sure why you're using an array here, as you seem to be outputting the last line of the ping only, anyway.  But maybe this is just an oversimplified example.

Replies are listed 'Best First'.
Re^2: Reading from a pipe
by hello_world (Acolyte) on Nov 20, 2011 at 13:51 UTC
    Thanks it works,Lets say if i fork 3-4 child processes and all of them write into the pipe,and on the parent side can i read at a time what all child processes wrote by doing a  @read_from_children = <$read>. Looks it doesn't work.I still have to do a loop and read.

      The problem is that the readline blocks until it has read a line (irrespective of whether you use it in list or scalar context). So despite your non-blocking waitpid(-1,WUNTRACED) you won't start a new child before the old one has written a line to the pipe. In other words, as you have it, your pings will still run sequentially (just as they would without the additional fork/wait wrapped around the backticks call).

      If you want to run several child processes in parallel, you'd have to have independent pipes, and (for example) read from them in a select loop when they're ready (the other form of select, that is, not the one you're already using in your code).

        Thanks for the explanation Eliya. Basically,i am writing a script which forks multiple processes which ping different hosts for 40-50 sec and report to the parent script with values. I'd like to do the pinging part in parallel,not sequentially. So,if i have a 10 child ping processes,do i need to create 10 different pipes ( hope i am getting this right).Lastly,what sort of IPC is better in such cases.
        Thanks for the explanation Eliya. Basically,i am writing a script which forks multiple processes which ping different hosts for 40-50 sec and report to the parent script with values. I'd like to do the pinging part in parallel,not sequentially. So,if i have a 10 child ping processes,do i need to create 10 different pipes ( hope i am getting this right).Lastly,what sort of IPC is better in such cases.