ignoring SIGCHLD

M

Moritz Karbach

Hi,

since my last question "How to kill a forked child process..." [1], I have
learned a little bit more.

I have adjusted the run() function of my Command class following all the
hints you gave me and it works.

But now I have the problem, that in the dmesg appears something like:
application bug: h1mcJobwrapper.(25668) has SIGCHLD set to SIG_IGN but
calls wait().
(see the NOTES section of 'man 2 wait'). Workaround activated.

But I never call Perl's wait() in my code! Nor do I call system's wait
explicitly.

Btw, I haven't found out yet what this is good for:

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

Btw2, if I'm redirecting STDERR of the forked child to STDOUT so that the
parent receives it as well, I have the a problem with executing shell
skripts that do something like

#!/bin/bash
somebinary &

The problem is, that the reading of the pipe

my @output = <$fh_child>;
close($fh_child);

blocks until somebinary has finished, although both the shell skript and the
sh -c interpreter called by Perl are done a lot earlier.


Nevertheless, here is the run function:

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

$SIG{CHLD} = "IGNORE";

#
# fork the program branch
#
my $pid;
$pid = open($fh_child,"-|");

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;

$SIG{TTIN} = "IGNORE";
$SIG{TTOU} = "IGNORE";

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

setpgrp(0,0);

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

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

if ( $this->{timeout} > 0 )
{
$wdog_id = fork;
die "cannot fork: $!\n" unless defined($wdog_id);

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

setpgrp(0,0);

sleep($this->{timeout});

#
# killing negative process id's also sends the signal to all
# other processes in the process-group of $pid
#
# In our case this would kill both the shell interpreter and
# the executable launched by the interpreter.
#
kill(9, -$pid);

exit 0;
}
}

#
# read output of the command
#
# this blocks until the command is finished!
#
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};
}
</code>

Cheers,

- Moritz

[1] <[email protected]>
 
A

Anno Siegel

Moritz Karbach said:
Hi,

since my last question "How to kill a forked child process..." [1], I have
learned a little bit more.

I have adjusted the run() function of my Command class following all the
hints you gave me and it works.

But now I have the problem, that in the dmesg appears something like:
application bug: h1mcJobwrapper.(25668) has SIGCHLD set to SIG_IGN but
calls wait().
(see the NOTES section of 'man 2 wait'). Workaround activated.

But I never call Perl's wait() in my code! Nor do I call system's wait
explicitly.

You don't, but close() does. From perldoc -f close:

Closing a pipe also waits for the process executing on the pipe
to complete...

Anno
 
A

Anno Siegel

Moritz Karbach said:
Is it really necessary to close the pipe then?

It can't stay open after your program finishes, can it? Every filehandle
is closed during global destruction.

Anno
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top