in reply to Re^6: Multiprocess - child process cannot be finished successfully
in thread Multiprocess - child process cannot be finished successfully
Your code here looks backwards. You need the alarm because presumably the network setup is a blocking operation? You need to set up the alarm and turn it on BEFORE you enter into code that potentially will "freeze".
I would suggest you make a safe_print() like I did to cut down on the "noise".eval { $var = #setup a network connection...; $SIG{ALRM} = sub { flock $fh, LOCK_EX; print $fh "\n"; flock $fh, LOCK_UN;}; alarm(60); };
Update: Added a time stamp to original code. preserved in readmore tags.
use strict; use warnings; use Fcntl qw(:flock); use File::Copy 'move'; use POSIX "sys_wait_h"; #for waitpid FLAGS use Time::Local; $|=1; my @child_sleeps = qw(10 15 12 5 12); my $start_epoch = time(); # Fire off number of child processes equal to the # number of elements in @child_sleeps; # Then the parent who started these little guys, # goes into a blocking wait until they all finish # Each child can return a status code via exit($code_number). # However, this code doesn't use that and instead assumes # that children and the parent are all writing to a common # file shared via a cooperative flock $SIG{CHLD} = 'IGNORE'; open(my $fh_log, '>>', "Alogfile.txt") or die "unable to open Alogfile +.txt $!"; #$fh_log->autoflush; #not needed this is automatic before locking or +unlocking a file! foreach my $sleep_interval (@child_sleeps) { if(my $pid = fork) { # parent safe_print ($fh_log, "Spawned child $pid lasting $sleep_interv +al seconds\n"); } elsif(defined $pid ) # pid==0 { # child safe_print ($fh_log, "This is child pid $$. I will sleep for $ +sleep_interval seconds!\n"); sleep($sleep_interval); safe_print ($fh_log, "Child $$ time is up!! I am gonna croak!\ +n"); exit(0); } else { # fork failed pid undefined die "MASSIVE ERROR - FORK FAILED with $!"; } } ### now wait for all children to finish, no matter who they are 1 while wait != -1 ; # avoid zombies this is a blocking operation safe_print ($fh_log, "Parenting talking...all my children are dead! Ho +oray!\n"); close $fh_log; #must close file before renaming it! unlink "Alogfile.back" if ( -e "Alogfile.back"); move "AlogFile.txt", "AlogFile.back" or die "unable to rename log file +! $!"; print "A happy ending!\n"; sub safe_print { my ($fh, @text) = @_; my $now_epoch = time(); my $delta_secs = $now_epoch - $start_epoch; flock $fh, LOCK_EX or die "flock can't get lock $!"; print $fh "$delta_secs secs: $_" foreach @text; print "$delta_secs secs: $_" foreach @text; flock $fh, LOCK_UN or die "flock can't release lock $!"; } __END__ Contents of AlogFile.back after a run: 0 secs: Spawned child -10680 lasting 10 seconds 0 secs: This is child pid -10680. I will sleep for 10 seconds! 0 secs: Spawned child -23840 lasting 15 seconds 0 secs: This is child pid -23840. I will sleep for 15 seconds! 0 secs: Spawned child -14556 lasting 12 seconds 0 secs: This is child pid -14556. I will sleep for 12 seconds! 0 secs: Spawned child -13972 lasting 5 seconds 0 secs: This is child pid -13972. I will sleep for 5 seconds! 0 secs: Spawned child -18600 lasting 12 seconds 0 secs: This is child pid -18600. I will sleep for 12 seconds! 5 secs: Child -13972 time is up!! I am gonna croak! 10 secs: Child -10680 time is up!! I am gonna croak! 12 secs: Child -14556 time is up!! I am gonna croak! 12 secs: Child -18600 time is up!! I am gonna croak! 15 secs: Child -23840 time is up!! I am gonna croak! 15 secs: Parenting talking...all my children are dead! Hooray! A happy ending!
use strict; use warnings; use Fcntl qw(:flock); use File::Copy 'move'; use POSIX "sys_wait_h"; #for waitpid FLAGS my @child_sleeps = qw(10 15 12 5 12); # Fire off number of child processes equal to the # number of elements in @child_sleeps; # Then the parent who started these little guys, # goes into a blocking wait until they all finish # Each child can return a status code via exit($code_number). # However, this code doesn't use that and instead assumes # that children and the parent are all writing to a common # file shared via a cooperative flock $SIG{CHLD} = 'IGNORE'; open(my $fh_log, '>>', "Alogfile.txt") or die "unable to open Alogfile +.txt $!"; #$fh_log->autoflush; #not needed this is automatic before locking or +unlocking a file! foreach my $sleep_interval (@child_sleeps) { if(my $pid = fork) { # parent safe_print ($fh_log, "Spawned child $pid lasting $sleep_interv +al seconds\n"); } elsif(defined $pid ) # pid==0 { # child safe_print ($fh_log, "This is child pid $$. I will sleep for $ +sleep_interval seconds!\n"); sleep($sleep_interval); safe_print ($fh_log, "Child $$ time is up!! I am gonna croak!\ +n"); exit(0); } else { # fork failed pid undefined die "MASSIVE ERROR - FORK FAILED with $!"; } } ### now wait for all children to finish, no matter who they are 1 while wait != -1 ; # avoid zombies this is a blocking operation close $fh_log; #must close file before renaming it! unlink "Alogfile.back" if ( -e "Alogfile.back"); move "AlogFile.txt", "AlogFile.back" or die "unable to rename log file +! $!"; print "A happy ending!\n"; sub safe_print { my ($fh, @text) = @_; flock $fh, LOCK_EX or die "flock can't get lock $!"; print $fh @text; flock $fh, LOCK_UN or die "flock can't release lock $!"; } __END__ Results from testing on Windows (they use a negative PID for their for +k emulation) Spawned child -20688 lasting 10 seconds This is child pid -20688. I will sleep for 10 seconds! Spawned child -19896 lasting 15 seconds This is child pid -19896. I will sleep for 15 seconds! Spawned child -24392 lasting 12 seconds This is child pid -24392. I will sleep for 12 seconds! Spawned child -24692 lasting 5 seconds This is child pid -24692. I will sleep for 5 seconds! Spawned child -20296 lasting 12 seconds This is child pid -20296. I will sleep for 12 seconds! Child -24692 time is up!! I am gonna croak! Child -20688 time is up!! I am gonna croak! Child -24392 time is up!! I am gonna croak! Child -20296 time is up!! I am gonna croak! Child -19896 time is up!! I am gonna croak!
Also, I don't see much need to write to the log file in case of flock(),fork() failure, perhaps you will do just as well with "die" for those super massive errors? Something is super wrong if the O/S cannot fork!
|
---|