How to kill a forked child process...

M

Moritz Karbach

....such that it doesn't become a zombie?

Hi,

I'm trying to implement something like this:

parent
|
|
|\ fork
| \
| \
| | child calls an system command,
| | exec("foo");
| |
fork /| |
/ | |
/ | |
watch- | | |
dog | | |
kills | | -
foo - |
|
|


But everytime the watchdog kills the child, the child becomes a zombie. Is
there a way to prevent this?

Here is some code (the run-function of my Command-class, which handles
system calls):

sub runFork # ()
{
my $this = shift;
my $fh_child; # pipe to the child process running the command

$pid = fork;
die "cannot fork: $!\n" unless defined($pid);

if ( $pid == 0 )
{
#
# child (command branch)
#
my @temp = ($EUID, $EGID);
my $orig_uid = $UID;
my $orig_gid = $GID;
$EUID = $UID;
$EGID = $GID;

# Drop privileges
$UID = $orig_uid;
$GID = $orig_gid;

# Make sure privs are really gone
($EUID, $EGID) = @temp;

die "Can't drop privileges"
unless $UID == $EUID && $GID eq $EGID;

open(STDERR, ">&STDOUT") or die "Can't dup STDOUT: $!";

$SIG{TTIN} = "IGNORE";
$SIG{TTOU} = "IGNORE";
$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";
setpgrp(0,0);

exec($this->{command}) or die ("cannot run program: $!");
exit;
}

#
# fork once more for the watchdog for the timeout
#
my $wdog_id;

$wdog_id = fork;
die "cannot fork: $!\n" unless defined($wdog_id);

if ( $wdog_id == 0 )
{
#
# child - watchdog branch
#
$SIG{TTIN} = "IGNORE";
$SIG{TTOU} = "IGNORE";
$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";
setpgrp(0,0);

sleep($this->{timeout});

kill(-9, $pid);
#`kill -9 $pid`;
exit;
}

#
# read output of the command
#
my @output = <$fh_child>;
close($fh_child);
$this->{output} = \@output;

#
# return value of the command
#
$this->{ret} = $?;
my $sig = $this->{ret} & 127;

#
# if command succeeded, we don't need the watchdog any more: kill!
#
if ( defined($wdog_id) && $sig != 9 )
{
kill(-9, $wdog_id);
}

return $this->{ret};
}
 
B

Brian McCauley

Moritz said:
...such that it doesn't become a zombie?

Hi,

I'm trying to implement something like this:

parent
|
|
|\ fork
| \
| \
| | child calls an system command,
| | exec("foo");
| |
fork /| |
/ | |
/ | |
watch- | | |
dog | | |
kills | | -
foo - |
|
|


But everytime the watchdog kills the child, the child becomes a zombie. Is
there a way to prevent this?

The parent process of the child (not the sibling) must wait() or ignore
$SIG{CHLD}.

Have the parent fork off the watchdog process, then have the watchdog
fork-and-exec.

This doesn't really have anything to do with Perl, this is a Unix question.
 
P

Paul Lalli

Moritz said:
Subject: How to kill a forked child process...
...such that it doesn't become a zombie?

I admit to not being overly proficient in the area of forking
processes, children, parents, zombies, and the like. That being said,
can you explain how the following does not provide an answer to your
question?

(I mean that seriously - it's good to know if there's reason to believe
the documentation should be updated)

perldoc -q zombie
Found in /opt/perl/lib/5.6.1/pod/perlfaq8.pod
How do I avoid zombies on a Unix system?

Use the reaper code from the Signals entry in the perlipc
manpage to call wait() when a SIGCHLD is received, or else
use the double-fork technique described in the fork entry in
the perlfunc manpage.

Have you read that entry? And have you read both perldoc perlipc and
perldoc -f fork, as they suggested?

Paul Lalli
 
M

Moritz Karbach

The parent process of the child (not the sibling) must wait() or ignore
$SIG{CHLD}.

Thanks for the hint. I moved the

$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";

to the parent and the zombies disappeared.
This doesn't really have anything to do with Perl, this is a Unix
question.

I'm sorry. Since both Perl and Unix signal handling are relatively new to
me, it's hard for me to distinguish.

Cheers,

- Moritz
 
M

Moritz Karbach

The parent process of the child (not the sibling) must wait() or ignore
$SIG{CHLD}.

Thanks for the hint. I moved the

$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";

to the parent and the zombies disappeared.
This doesn't really have anything to do with Perl, this is a Unix
question.

I'm sorry. Since both Perl and Unix signal handling are relatively new to
me, it's hard for me to distinguish.

Cheers,

- Moritz
 
M

Moritz Karbach

The parent process of the child (not the sibling) must wait() or ignore
$SIG{CHLD}.

Thanks for the hint. I moved the

$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";

to the parent and the zombies disappeared.
This doesn't really have anything to do with Perl, this is a Unix
question.

I'm sorry. Since both Perl and Unix signal handling are relatively new to
me, it's hard for me to distinguish.

Cheers,

- Moritz
 
M

Moritz Karbach

The parent process of the child (not the sibling) must wait() or ignore
$SIG{CHLD}.

Thanks for the hint. I moved the

$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";

to the parent and the zombies disappeared.
This doesn't really have anything to do with Perl, this is a Unix
question.

I'm sorry. Since both Perl and Unix signal handling are relatively new to
me, it's hard for me to distinguish.

Cheers,

- Moritz
 
M

Moritz Karbach

The parent process of the child (not the sibling) must wait() or ignore
$SIG{CHLD}.

Thanks for the hint. I moved the

$SIG{CHLD} = "IGNORE";
$SIG{CLD} = "IGNORE";

to the parent and the zombies disappeared.
This doesn't really have anything to do with Perl, this is a Unix
question.

I'm sorry. Since both Perl and Unix signal handling are relatively new to
me, it's hard for me to distinguish.

Cheers,

- Moritz
 
L

Larry

Incidentally, be careful. You are using a negative signal number in
your "kill" call. Remember, when you do "kill -9" from the shell, that
dash is an option specifier not a minus sign. The signal you are
sending is +9.
 
A

a

This is a suggestion not an answer...

Look at "Parallel::Forkmanager" perl mod..

I was trying to do a similiar task and gave up
(the process of following threads was mind binding) ...

some1 on this group mentioned the mod and
i've been quite happy since...


Joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top