SPUG: Question on fork() and pipe()

Dwyer, Sean sean.dwyer at attws.com
Mon May 13 11:21:42 CDT 2002


All, 

	I have run into a bind on a control structure I am working with.
Although I have a work around, I would rather use the pipe() solution so I
can pass more complex data back to the parent process. The test code is
below. Here is what is happening. The test sequence should spawn 5 children
and as they die off replace them to maintain a running count of 5 until the
whole list (in this case a simple counter totaling at 20) is complete.
Without the pipe() for communication between the children and the parent it
acts just as it is supposed to. When I add the pipe in the processes
serializes. 

	My workaround is to use the exit status to give partial information
back to the parent. But .. using the pipe allows me to pass more data back
to the parent for later processes. If I use exit status then I will need to
send the additional output to flat file so the parent can pick is up later
and I would rather not do that.

	I have noted that from the OS (HPUX 11.00) side that the parent goes
into a sleep state waiting on the pipe. Is there a way to leave the pipe
open so that the children can talk back to the parent and still parallelise?
If so what am I missing and how do I do it. Thanks in advance for any help.

Sean Dwyer 

Data Base Administrator
Customer Operations Support
National Data Center Operations
AT&T Wireless Services, Inc.
Bothell, Washington
Desk-425.288.7313
Cell-206.601.5465

#!/usr/local/perl5/bin/perl -w

use POSIX ":sys_wait_h";
use IO::Handle;
use strict;

$| = 1; 


my ($exit_val, $signal_num, $dumped_core);

$SIG{CHLD} = \&child_track; 
			    
my $DEBUG = 0;
my $counter = 0;
my $child = 0;


print "\n## The parent process is: $$ \n";

##
## I have set a for loop here to take the place of the array 
## that I really process in order to limit my number of iterations
##
for (my $i = 1; $i <= 20; $i++) {
  $counter++; # increase the counter because we are about to fork a child
  print "COUNTER: $counter  \n";
  &fork_child(); #fork the child passing in a vaiable
  while ($counter >= 5) {
    sleep 1; #sleep the processes so that we don't spin up the CPU
    while ((my $child = waitpid(-1, -2)) > 0){1;} #wait on 1, any 1 child 
                                                  #to exit
    }
  }

waitpid(-1, 0); # wait on all children to exit before ending.


sub fork_child {
  FORK: {

    pipe(READER, WRITER);
    WRITER->autoflush(1);

    if (my $pid = fork()) { # parent here
      close WRITER;
      chomp(my $line = <READER>);
      print "There Parent pid $$ just read this: '$line'\n";
      close READER;
      next if $child == 1; # Do not fork a child from a child
      } 
    elsif (defined $pid) { # $pid is zero here if defined
                           # child here
      $child = 1; 

      sleep int(rand 10); #this is where the real work would go
                          #randomize the sleep so the children don't
                          #all exit at once.
            
      close READER;
      print WRITER "Child pid $$ is sending this";
      close WRITER;

      exit 100;
      } 
    elsif ($! =~ /No more process/) { # EAGAIN, supposedly recoverable 
                                      # fork error
      sleep 5;
      redo FORK;
      } 
    else { # weird fork error
      die "Can't fork: $!\n";
      }
    }
  }

sub child_track {
  my $pid = waitpid(-1, 0);
  if ($pid == -1){return;} #no children have exited
  elsif (WIFEXITED($?)) {
    $exit_val = $? >> 8;
    $signal_num = $? & 127;
    $dumped_core = $? & 128;
#    print "\$pid = $pid\n";
#    print "\$signal_num = $signal_num\n";
#    print "\$exit_val = $exit_val\n";
#    print "\$dumped_core = $dumped_core\n";
    print "Process exited\n";
    $counter --; #decrease the counter so that you can spawn another
processes
    return;
    }
  else {print "False alarm on $pid";} #any other values are considered false

  $SIG{CHLD} = \&child_track; #re-install the handler 
  }


 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     POST TO: spug-list at pm.org       PROBLEMS: owner-spug-list at pm.org
      Subscriptions; Email to majordomo at pm.org:  ACTION  LIST  EMAIL
  Replace ACTION by subscribe or unsubscribe, EMAIL by your Email-address
 For daily traffic, use spug-list for LIST ;  for weekly, spug-list-digest
     Seattle Perl Users Group (SPUG) Home Page: http://seattleperl.org




More information about the spug-list mailing list