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

I have a bit of a quandry.
I'm running a number of forked processes in a program. The name and number of these processes varies from each running of this program, so they are called using an iterative loop.

I've managed to get the processes to run concurrently, using fork and pipe, but there isn't a mechansim to pass the output back to the parent program, which I need to do. I know I have the option of creating a temp file, but that becomes a problem when multiple users are running this program (web based).

I was thinking of creating a filename based on rand(), but them someone suggested I look at IO::Select. Problem is, every example I see uses sockets, and that's not really necessary in this situation. The forked processes being run are from a group of custom 'handlers' I've written. All the scripts are in one location, so they will always run from that place. Can IO::Select be used here without creating sockets? If so, how can I use it to harvest the output of these processes?

Replies are listed 'Best First'.
Re: IO::Select - is it right for this?
by Skeeve (Parson) on Oct 20, 2003 at 13:06 UTC
    can't you simply use the open on "-|" in order to read output from your child?
    while ($more_childs_to_produce) { $pid= open($child[$childnumber++], "-|"); if ($pid) { # parent # here we have another "file" # to read frome with <$child[$childnumber-1]> } else { # child # Do the child's work and exit; } }
    Taken from perldoc perlipc
      for ($i=0; $i<`#of children to do`; $i++;) { $pid[$i]= open($created_file_handle, "$custom_call_statement -|"); if ($pid[$i]) { waitpid($pid[$i], 0); } # parent waits for child to + finish } else { while (<$created_file_handle>) { $out[$i] .= $_; } # add outpu +t to the array exit; } }
      Problem is, and it's the same when forking, that the parent can't see @out. Should I move the $out[$i] .= $_; to the parent process? The forked processes work fine, and fairly quickly, but I need to get the child to tell the parent what it found.

      I'd rather not have to use the temp file solution, as it will get very messy when having multiple users run multiple processes at the same time. That's going to make this whole process run a lot slower. I'd rather see if I can find a solution that passes data faster back to the main process.
        To be honest... I really don't understand your code above. Sorry...
        But then... Here is a complete program that might help you. It forks 2 children and collects the children's output in an array.
        Be aware that there is no error handling (can't fork etc.) yet.
        use warnings; use strict; my $children= 2; # How many to fork my @out; my $first_child; $|=1; # unbuffered output to see the effect my $pid= open($first_child, '-|'); if ($pid) { # parent: Collects all output @out= <$first_child>; } else { # child forks again and produces output my(@child, @childpid); for (my $i=0; $i<$children; ++$i) { $childpid[$i]= open($child[$i], '|-'); if ($childpid[$i]) { # parent # does nothing yet } else { # child produces some output my $j=10; while ($j--) { print "I'm child $i and will tell this $j more time(s) +\n"; sleep 1; } exit; } } foreach (@child) { # closing all child handles close $_; } exit; } print @out;
Re: IO::Select - is it right for this?
by ptkdb (Monk) on Oct 20, 2003 at 13:11 UTC
    IO::Select is a package that allows you to monitor a group of sockets to see if they have data waiting to be read, or there is available space that can be written.

    If the passage of data is 'one-way', that is to say the master program is only going to collect results from the child program/process after it's completed, a temp file is much simpler.

    If all of the processes are running on the same machine, then you can use the process id($$) of a process as part of the filename, since the process id is guaranteed to be unique.

Re: IO::Select - is it right for this?
by Zaxo (Archbishop) on Oct 21, 2003 at 03:49 UTC

    Yes, IO::Select is right for this.

    IO::Select will work fine for filehandles other than sockets. You just need to give the fileno of the handle as argument to the IO::Select instance's add() method, or else wrap the pipe's output handle in IO::Handle and use that object as the argument.

    After Compline,
    Zaxo