Ok, I'm back from my meeting and wrote some more code for you.

Some changes:
- while ( sleep(1), @dead_kids < @all_kids) {} will wait until the number of dead_kids is the same as all_kids. note: scalar in front of @all_kids is redundant. I've used both of these arrays in a scalar context. The sleep() is so that we don't burn CPU while looping. Handling SIGCHLD seems to prematurely end the sleep, but this code restarts the sleep if we aren't done. In Perl I think sleep() is implemented in terms of alarm() and I will admit something a bit weird is going on here that I don't fully understand although my workaround appears to be fine.

- the $SIG{INT} = 'IGNORE'; in the child code is important. If you leave it in there, then hitting CTL-C will print the the currently running kids and then resume normal operation. If you comment that line out, then normal CTL-C handling is in effect for the children and they will exit. The CTL-C handler is only installed for the parent. The child either ignores CTL-C or has normal handling for it. On my Linux test machine, when this code is running in the foreground, everybody (all kids and the parent) get CTL-C if I hit that.

Interesting problem. Have fun with this code. I didn't worry about efficiency in sub ctlc - I think the main point here is how to handle the signals and what to do when.

#!/usr/bin/perl -w use strict; use POSIX qw(:sys_wait_h); $SIG{CHLD} = \&REAPER; $|=1; #turn off STDOUT buffering my (@all_kids, @dead_kids); my @array = qw(a b c d e f g h); for (1 .. 10) { die "Bad Fork! $!\n" if ( !defined(my $pid = fork()) ); if ($pid ==0) #I'm child { $SIG{INT} = 'IGNORE'; #### comment out to exit on CTL-C my $t = int(rand(5))+1; print "@array sleeping $t secs\n"; sleep ($t); exit (0); } push (@all_kids, $pid); #I'm parent print "Started another child process - $pid.\n"; } print "All child processes have started...\n"; print "kids are: @all_kids\n"; $SIG{INT} = \&ctlc; #CTL-C handler in parent only while ( sleep(1), @dead_kids < @all_kids) {} #wait for kids to finish print "dead kids: @dead_kids\n"; print "All child processes are finished\n"; sub REAPER { my $pid; while ( ($pid = waitpid(-1, WNOHANG)) > 0) { print "Process $pid exited.\n"; push @dead_kids, $pid; } } sub ctlc { print "***** Ctrl-C Trap\n"; my %dead = map{$_ => 1}@dead_kids; print "still alive: "; foreach my $kid (@all_kids) { print "$kid " if !$dead{$kid}; } print "\n"; print "***** Ctrl-C Trap end\n"; }

In reply to Re^5: Monitoring Child Process by Marshall
in thread Monitoring Child Process by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.