Beefy Boxes and Bandwidth Generously Provided by pair Networks Cowboy Neal with Hat
Perl Monk, Perl Meditation
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??

No, just sleeping won't do the trick. It will bite you again as soon as one of your forked processes needs longer than that. And it will waste resources and your time if all of your forked processes are faster than the delay.

Use the proper way: Remember the PIDs of the forked processes, and wait() for all of your forked processes. End your main process when you have waited for all processes.

Stupid example:

#!/usr/bin/perl use 5.010; use strict; use warnings; $|=1; # autoflush my %pids; for (1..10) { my $pid=fork() // die "Can't fork: $!"; if ($pid) { # parent, remember PID $pids{$pid}++; say "Forked child $_, PID=$pid"; } else { # child say "Child process $_"; sleep (5+rand(5)); exit 0; } } while (%pids) { my $pid=wait(); delete $pids{$pid}; say "child with PID $pid exited"; } say "all childs exited";

If you want to do some work in your parent process, rely on SIGCHLD instead. SIGCHLD will be sent to your parent process as soon as a child process exits.

Stupid example:

#!/usr/bin/perl use 5.010; use strict; use warnings; use POSIX ":sys_wait_h"; $|=1; # autoflush my %pids; sub reaper { $SIG{CHLD}=\&reaper; # This does not work, because you may get only one signal when # two or more processes exit at nearly the same time. This is due # to the way signals are implemented. #my $pid=wait(); #delete $pids{$pid}; my $pid; do { $pid=waitpid(-1, WNOHANG); delete $pids{$pid}; } while $pid>0; } $SIG{CHLD}=\&reaper; for (1..10) { my $pid=fork() // die "Can't fork: $!"; if ($pid) { # parent, remember PID $pids{$pid}++; say "Forked child $_, PID=$pid"; } else { # child $SIG{CHLD}='DEFAULT'; # maybe not needed, but doesn't hurt say "Child process $_"; sleep (5+rand(5)); exit 0; } } while (keys %pids) { say "Parent is working, ",scalar keys %pids," children still alive + (PIDS ",join(', ',keys %pids),")..."; sleep 1; } say "all childs exited";

Note that you should keep the signal handler routine as short as possible, and that you should avoid any I/O there. Just set or clear a flag and return as fast as possible. With modern Perl implementations, you usually have "safe signals" that allow to do more in a signal handler, but you can disable them for speed or other special purposes. And in older Perl implementations, unsafe signals are standard and WILL bite you very fast.

And now, propagating SIGINT:

You know the PIDs of all of your child processes, because you need them for wait()/waitpid(). So it is no problem to use it to send SIGINT to your child processes:

#!/usr/bin/perl use 5.010; use strict; use warnings; use POSIX ":sys_wait_h"; $|=1; # autoflush my %pids; sub reaper { $SIG{CHLD}=\&reaper; # This does not work, because you may get only one signal when # two or more processes exit at nearly the same time. This is due # to the way signals are implemented. #my $pid=wait(); #delete $pids{$pid}; my $pid; do { $pid=waitpid(-1, WNOHANG); delete $pids{$pid}; } while $pid>0; } $SIG{CHLD}=\&reaper; sub sigint { $SIG{INT}=\&sigint; kill INT => keys %pids; } $SIG{INT}=\&sigint; for (1..10) { my $pid=fork() // die "Can't fork: $!"; if ($pid) { # parent, remember PID $pids{$pid}++; say "Forked child $_, PID=$pid"; } else { # child $SIG{CHLD}='DEFAULT'; # maybe not needed, but doesn't hurt $SIG{INT}='DEFAULT'; say "Child process $_"; sleep (5+rand(5)); exit 0; } } while (keys %pids) { say "Parent is working, ",scalar keys %pids," children still alive + (PIDS ",join(', ',keys %pids),")..."; sleep 1; } say "all childs exited";

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

In reply to Re^3: SIG{INT} not handling CTRL-C ??? by afoken
in thread SIG{INT} not handling CTRL-C ??? by girishatreya2005

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!
  • 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, 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, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            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.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others romping around the Monastery: (6)
    As of 2014-04-19 02:41 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      April first is:







      Results (475 votes), past polls