Re: Monitoring multiple child processes
On Nov 10, 12:35 pm, shawnhco...@gmail.com (Shawn H Corey) wrote: C.DeRykus wrote: On Nov 9, 3:31 am, shawnhco...@gmail.com (Shawn H Corey) wrote: redo if $kid != $child_pid; Hm, I'm not sure why you'd want to 'redo' in the case of a blocking wait. As I read the docs, a blocking wait on a specific pid returns only that pid if reaped normally or -1 if there's no such pid (or that pid's been already reaped). In either case, I'd think you'd just want to continue processing the pid loop. From `perldoc -f waitpid`: On some systems, a value of 0 indicates that there are processes still running. I see that but I suspect Perl's waitpid doc is unintentionally misleading. A quick look at Linux and OpenBSD wait(2) manpages specifies a 0 return can occur only with FLAGS set to WNOHANG. OpenBSD: from waitpid(2) manpage: Otherwise, if WNOHANG is specified and there are no stopped or exited children, 0 is returned. Linux: ... if WNOHANG was specified and no child(ren) specified by pid has yet changed state, then 0 is returned. Can anyone confirm an O/S with different semantics for wait(2)'s return...? In other words, waitpid can return a value which is not the pid of the child you requested. Therefore redo, since it's a foreach loop. This, of course, is only true on some systems; it may not be true on yours. If there's a system where a blocking waitpid could return something other than -1 or the specific pid you waited on, that'd be true. But, even then, you'd have to be careful that a -1 indicating a reaped process didn't cause an endless loop due to the 'redo'. -- Charles DeRykus -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
RE: Monitoring multiple child processes
On some systems, waitpid may return something rather than a child pid or -1. This would happen when the wait was interrupted by something other than a child death. Most likely, it would be zero. The return status, $?, is a 16-bit word of three packed values. See `perldoc perlvar` and search for /\$\?/. It should be set to a non-zero value by the child if the child does not terminate successfully. Most UNIX commands do this; most user-written scripts do not. Also, Windows ignores the return value and always returns zero. $? should not change unless a child process died. Ahhh, I see. I think I understand now. Thankyou for your help and explanations. Andy Capgemini is a trading name used by the Capgemini Group of companies which includes Capgemini UK plc, a company registered in England and Wales (number 943935) whose registered office is at No. 1 Forge End, Woking, Surrey, GU21 6DB. This message contains information that may be privileged or confidential and is the property of the Capgemini Group. It is intended only for the person to whom it is addressed. If you are not the intended recipient, you are not authorized to read, print, retain, copy, disseminate, distribute, or use this message or any part thereof. If you receive this message in error, please notify the sender immediately and delete all copies of this message. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Monitoring multiple child processes
On Nov 9, 3:31 am, shawnhco...@gmail.com (Shawn H Corey) wrote: Taylor, Andrew (ASPIRE) wrote: Hello I have a script that, much like the Little Old Lady who lived in a shoe, has so many children it's not sure what to do. Basically, the script does some stuff, then kicks off multiple copies of an external process that all run in parallel. It then has to wait until all of them have completed (successfully) then carry on with the next bit. What I've cobbled together so far (i.e. swiped of the web then modified...) use strict; use warnings; # Do some stuff here for (my $i=1; $i =$num_processes; $i++) for my $i ( 1 .. $num_processes ) { defined(my $pid = fork) or die( Cannot fork : $!\n); # Put all the pids into an aray if ($pid) { push @pids, $pid; } else { exec external giggery pokery } } foreach my $child_pid (@pids) { waitpid($child_pid, 0); my $kid = waitpid($child_pid, 0); unless( 0==$? ) { die (Oh No! An external process has failed!!\n); } redo if $kid != $child_pid; Hm, I'm not sure why you'd want to 'redo' in the case of a blocking wait. As I read the docs, a blocking wait on a specific pid returns only that pid if reaped normally or -1 if there's no such pid (or that pid's been already reaped). In either case, I'd think you'd just want to continue processing the pid loop. In contrast (at least on POSIX compliant OS's), a non-blocking blocking wait with -1 rather than a specific pid could potentially reap other pid's: use POSIX :sys_wait_h; #... do { $kid = waitpid(-1, WNOHANG); } while $kid 0; This might reap an extraneous process such as one launched via backticks maybe in an forked pid for instance. On some systems, waitpid may return for any interrupt, not just when the child terminates. Also the POSIX non-blocking wait has the advantage in that case by providing macro's that can reveal some additional exit/termination status: use POSIX :sys_wait_h; ... $kid = waitpid( -1, WNOHANG); print $kid: signal termination if WIFSIGNALED($?); -- Charles DeRykus -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Monitoring multiple child processes
C.DeRykus wrote: On Nov 9, 3:31 am, shawnhco...@gmail.com (Shawn H Corey) wrote: redo if $kid != $child_pid; Hm, I'm not sure why you'd want to 'redo' in the case of a blocking wait. As I read the docs, a blocking wait on a specific pid returns only that pid if reaped normally or -1 if there's no such pid (or that pid's been already reaped). In either case, I'd think you'd just want to continue processing the pid loop. From `perldoc -f waitpid`: On some systems, a value of 0 indicates that there are processes still running. In other words, waitpid can return a value which is not the pid of the child you requested. Therefore redo, since it's a foreach loop. This, of course, is only true on some systems; it may not be true on yours. -- Just my 0.0002 million dollars worth, Shawn Programming is as much about organization and communication as it is about coding. I like Perl; it's the only language where you can bless your thingy. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Monitoring multiple child processes
Taylor, Andrew (ASPIRE) wrote: Hello I have a script that, much like the Little Old Lady who lived in a shoe, has so many children it's not sure what to do. Basically, the script does some stuff, then kicks off multiple copies of an external process that all run in parallel. It then has to wait until all of them have completed (successfully) then carry on with the next bit. What I've cobbled together so far (i.e. swiped of the web then modified...) use strict; use warnings; # Do some stuff here for (my $i=1; $i =$num_processes; $i++) for my $i ( 1 .. $num_processes ) { defined(my $pid = fork) or die( Cannot fork : $!\n); # Put all the pids into an aray if ($pid) { push @pids, $pid; } else { exec external giggery pokery } } foreach my $child_pid (@pids) { waitpid($child_pid, 0); my $kid = waitpid($child_pid, 0); unless( 0==$? ) { die (Oh No! An external process has failed!!\n); } redo if $kid != $child_pid; } On some systems, waitpid may return for any interrupt, not just when the child terminates. -- Just my 0.0002 million dollars worth, Shawn Programming is as much about organization and communication as it is about coding. I like Perl; it's the only language where you can bless your thingy. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
RE: Monitoring multiple child processes
my $kid = waitpid($child_pid, 0); redo if $kid != $child_pid; # So goes back to start of loop from here unless( 0==$? ) # And never performs this test { die (Oh No! An external process has failed!!\n); } } That makes most sense to me but I'm not sure how to test if my assumption is correct. (I'd have to somehow get the system to return a pid/status for a different process) In general, you will want to test for errors as soon as possible. If you get an error, how do you know waitpid will ever work correctly again? OK, I'm clearly being dense here then. My understanding was that the $? contained the status of the pid returned by waidpid. If waitpid returned a pid from some other process (i.e. not one of my children) that had failed (i.e return status other than 0) then wouldn't my test abort the script when it wouldn't need to (as the process that failed wasn't one of my children) before it got to the redo? Or have I firmly grasped the wrong end of the stick? Capgemini is a trading name used by the Capgemini Group of companies which includes Capgemini UK plc, a company registered in England and Wales (number 943935) whose registered office is at No. 1 Forge End, Woking, Surrey, GU21 6DB. This message contains information that may be privileged or confidential and is the property of the Capgemini Group. It is intended only for the person to whom it is addressed. If you are not the intended recipient, you are not authorized to read, print, retain, copy, disseminate, distribute, or use this message or any part thereof. If you receive this message in error, please notify the sender immediately and delete all copies of this message. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Monitoring multiple child processes
Taylor, Andrew (ASPIRE) wrote: OK, I'm clearly being dense here then. My understanding was that the $? contained the status of the pid returned by waidpid. If waitpid returned a pid from some other process (i.e. not one of my children) that had failed (i.e return status other than 0) then wouldn't my test abort the script when it wouldn't need to (as the process that failed wasn't one of my children) before it got to the redo? Or have I firmly grasped the wrong end of the stick? On some systems, waitpid may return something rather than a child pid or -1. This would happen when the wait was interrupted by something other than a child death. Most likely, it would be zero. The return status, $?, is a 16-bit word of three packed values. See `perldoc perlvar` and search for /\$\?/. It should be set to a non-zero value by the child if the child does not terminate successfully. Most UNIX commands do this; most user-written scripts do not. Also, Windows ignores the return value and always returns zero. $? should not change unless a child process died. -- Just my 0.0002 million dollars worth, Shawn Programming is as much about organization and communication as it is about coding. I like Perl; it's the only language where you can bless your thingy. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/