Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

comment on

( [id://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":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (6)
As of 2024-03-19 09:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found