Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!usc!apple!agate!ucbvax!hplabs!hpcc05!hpcc01!okamoto From: okamoto@hpcc01.HP.COM (Jeff Okamoto) Newsgroups: comp.lang.perl Subject: Problem with waitpid? Message-ID: <1180006@hpcc01.HP.COM> Date: 5 Dec 90 18:14:24 GMT Organization: Tendou Dojo Lines: 145 I'm having a strange problem and I'm hoping someone out there may be able to help me. What I'm trying to do is write a perl script that will handle all the myriad daily cleanup things that need to be done. I envisioned having a single file which contains the names of programs and/or scripts. The perl program would execute each of these in turn, collecting the stdout and stderr from them, sending the stdout and/or stderr to each "owner" of a particular script. To this end, I've written a perl library which handles the ugly task of fork/exec/waiting and collecting the stdout and stderr. It is enclosed below. (Notice the waitpid call. I don't recall when it first made its appearance.) The actual problem I'm having is that one of the scripts that I fire off becomes defunct and the perl library doesn't catch it. Thus the perl script hangs until I kill it. I've confirmed that the PID that the perl library starts up is the same as the defunct PID, and that it is (was) the script in question. I can actually get the shell script to work IF I don't call ANOTHER script which starts up a daemon (to handle networked software installation). The flow of control is thus: nightly (the original perl script) | | <--- nightly.cf (it's configuration file) V n.test (contained in nightly.cf) | V startinstall (called from n.test) | V installd (the daemon mentioned above) I've confirmed that it's the attempt to start up installd that is the problem. Installd is a "well-behaved" daemon in that it disassociates itself from the control terminal, resets its process group, etc. I'm running patchlevel 41 on a 7.0 HP-UX machine. I'd really appreciate any suggestions or help that anyone could give. -- \ oo The New Number Who, \____|\mm Jeff Okamoto //_//\ \_\ HP Corporate Computing & Services /K-9/ \/_/ okamoto@ranma.corp.hp.com /___/_____\ ----------- (415) 857-6236 -----Begin file ;# ;# Perl library to fork/exec a program and return the standard out ;# and standard error in a list ;# ;# Jeff Okamoto ;# ;# $Header: execute.pl,v 1.1 90/10/17 15:11:38 okamoto Exp $ ;# Parameters: ;# ;# In: $program is a string that contains the command line of the ;# program to run. ;# $uid is the UID to run the program as. If $uid == -1, it is ;# run as the invoking UID. ;# Out: *retp is a list that will contain the standard out and ;# standard error of the program. *retp should be empty ;# before execute is called. ;# Return value: The high eight bits of the wait return value ;# are returned. sub execute { local($program) = shift(@_); # Program to run local($uid) = shift(@_); # Uid to run program as local($debug) = shift(@_); local(*retp) = shift(@_); # Array to hold stdout/stderr local($pid); # Hold child pid local($rv); # Hold return from wait local(@temp); push(@retp, "Here I am!\n"); if (! pipe(TOREAD, TOWRITE)) { push(@retp, "Pipe failed: $!"); $| = $oldbuffer; return(-1); } $pid = fork; if ($debug) { push(@retp, "Fork'ed PID was $pid.\n"); } if ($pid == -1) { push(@retp, "Fork failed: $!"); close(TOREAD); close(TOWRITE); $| = $oldbuffer; return(-1); } if ($pid == 0) { close(TOREAD); close(STDOUT); open(STDOUT, ">&TOWRITE"); select(STDOUT); $| = 1; close(STDERR); open(STDERR, ">&TOWRITE"); select(STDERR); $| = 1; close(TOWRITE); if ($uid != -1) { # Try to change uid $> = $uid; if ($> != $uid) { printf STDERR "Setuid failed: $!"; exit(-2); } } exec ("$program"); printf STDERR "Can't exec: $!"; exit(-1); } else { close(TOWRITE); @temp = ; # Slurp up the output. push(@retp, @temp); close(TOREAD); $whodied = waitpid($pid, 0); # Wait for the correct child $rv = $? >> 8; if ($debug) { $r = sprintf("Reaped PID %d, status = %o\n", $whodied, $?); push(@retp, $r); } } return($rv); } 1; -----End file Brought to you by Super Global Mega Corp .com