hambo has asked for the wisdom of the Perl Monks concerning the following question:
- can't keep a good language down!
Ok, so here's the problem.I have a program that needs to fork 3 children to do a job. On the children dying, I need to update a memory cache variable. I do this with a $SIG{CHLD}.
sub childDone { # Resource is freed up so place it back in the queue to be used fo +r future toasts. # $SIG{CHLD} = \&childDone; my $chld; $chld = waitpid(-1, WNOHANG) until $chld; return unless $chld > 0; #print "\n$$ sees $chld is done"; system(`touch /tmp/child.$chld`); # Toasting using this resource is now done my $str="toasting." . $jobs{$chld}; $cache->set($str,0); #print "\tresource " . $jobs{$chld} . " is free again!\n"; push @resource, $jobs{$chld}; #print "The resources to use are: @resource\n"; delete $jobs{$chld}; alarm 0; # send SIGALRM so sleep() wakes up }; $SIG{CHLD} = \&childDone;
What actually stopped working is that the children did not all call the signal handler when they died.
Below is the code that is responsible for forking the children:
@resources = {cdrw0 cdrw1 cdrw2} my $chld; while (@thisround) { my @sort_resource = sort(@resource); @resource = @sort_resource; while (@resource) { last unless @thisround; my $resource = shift @resource; my $data = shift @thisround; if (($chld = fork()) > 0) { # parent code # % jobs holds pid -> resource $jobs{$chld} = $resource; } else { # child code runcmd($resource, $data); exit; # end chld, trigger $SIG{CHLD} } } sleep until @resource == $num_resources; last unless @thisround; } sleep until keys %jobs == 0; # wait for all jobs
Now, within the subroutine
runcmd, I call the system command to do the job. I have tried the following:
B)system "cdrecord", "-immed", "-dummy", "-eject", "gracetime=$gracetime", "-tao", "dev=$resource", "$distroDirs{$distro}/$data";
Here the signal handler is called fine, but the problem is that the "cdrecord" is producing output that is really screwing with the look of the webpage displaying the results.
C)
my $pid = open (SAFEKID, "-|"); if ( $pid == 0 ) { open STDERR, ">/dev/null"; exec("cdrecord", "-immed", "-dummy", "-eject", "grace +time=$gracetime", "-tao", "dev=$resource", "$distroDirs{$distro}/$da +ta"); } else { my @output = <SAFEKID>; close SAFEKID; }
Why should these 3 commands work so differently?
How do I rework this so that I call the external program but discard the output, and still end up calling my custom signal handler when the child dies?
I have "cribbed" most of this from the Perl Cookbook and others, so if it looks as if I don't know what I'm talking about then looks are probably not that deceiving.
Any help would be a great relief to me, my family (they've had to put up with all the cussing) and of course my boss.
Thanks.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Invoking an external command - differences
by Roy Johnson (Monsignor) on Feb 07, 2005 at 19:43 UTC | |
|
Re: Invoking an external command - differences
by RazorbladeBidet (Friar) on Feb 07, 2005 at 20:36 UTC |