Killing all child processes upon parent exit

B

bsder

Hi,

Could anyone please tell me how to kill all child processes when parent
exit?

Here is the server code:

#!/usr/bin/perl

use strict;
use Socket;
use Data::Dumper;

# forward declaration
sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }

$SIG{INT} = $SIG{TERM} =$SIG{HUP} = \&signal_handler;
$SIG{CHLD} = 'IGNORE';
$SIG{CLD} = 'IGNORE';

my %kids = {};
my $proto = getprotobyname('tcp');
socket(SOCK,PF_INET,SOCK_STREAM,$proto) || die "socket : $!";
my $port = 7888;
my $address = pack_sockaddr_in($port, INADDR_ANY);

bind(SOCK, $address) || die "bind : $!";

while (1) {
listen(SOCK, SOMAXCONN) || die "listen: $!";
my $hostName = inet_ntoa(INADDR_ANY);
logmsg "server started on port $port, $hostName";

sub REAPER {
my $waitedpid = wait;
$SIG{CHLD} = \&REAPER;
logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
}
$SIG{CHLD} = \&REAPER;

print STDOUT "Server host: $hostName\n";
print STDOUT "Server port: $port\n";
(my $addr = accept(NEWSOCK,SOCK)) or ($! eq 'Interrupted system
all' and redo) or die $!;
select(NEWSOCK); $| = 1; select(STDOUT);

my $kidpid;
if (!defined($kidpid = fork())) {
die "cannot fork: $!";
}
elsif ($kidpid == 0) { # child
my ($cPort, $cHost) = unpack_sockaddr_in($addr);
my $cHostName = inet_ntoa($cHost);
print STDOUT "Client host: $cHostName\n";
print STDOUT "Client port: $cPort\n";
print NEWSOCK "Welcome to Code Generator.\r\n";

while (my $m=<NEWSOCK>) {
$m =~ s/\n|\r//g;
last if ($m eq ".");
print NEWSOCK "Server received $m\r\n";
}
close(NEWSOCK) || die "close in child: $!";
delete %kids->{$kidpid};
exit;
}
}


sub signal_handler
{
local $SIG{HUP} = 'IGNORE';
kill HUP => -$$;
print STDOUT "going to die\n";
exit;
}

Client code:
#!/usr/bin/perl


$domain = 2; # Internet domain
$type = 1; # Sequenced, reliable, two-way connection, byte streams
$proto = 6; # Transmission Control Protocol (TCP)
socket(SOCK,$domain,$type,$proto);
$host = pack('C4', 127,0,0,1); # localhost = 127.0.0.1
$port = 1024;
$address = pack('S n a4 x8', $domain, $port, $host);
bind(SOCK, $address);
print STDOUT "Client host: ",join('.',unpack('C4', $host)),"\n";
print STDOUT "Client port: $port\n";
$sHost = pack('C4', 127,0,0,1); # localhost = 127.0.0.1
$sPort = 7888;
$sAddress = pack('S n a4 x8', $domain, $sPort, $sHost);
connect(SOCK, $sAddress);
print STDOUT "Server host: ",join('.',unpack('C4', $sHost)),"\n";
print STDOUT "Server port: $sPort\n";
select(SOCK); $| = 1; select(STDOUT);
while ($m=<SOCK>) {
print STDOUT $m;
$m = <STDIN>;
print SOCK $m;
}
close(SOCK);
exit;

Thanks
Sam
 
A

Anno Siegel

bsder said:
Hi,

Could anyone please tell me how to kill all child processes when parent
exit?

What's the problem? You have the PID, Perl has the kill() function.

Anno
 
B

bsder

Anno said:
What's the problem? You have the PID, Perl has the kill() function.

Anno

Yes I have added the kill() function in the signal_handler(), is this a
proper way to add kill() function in signal handler?

Thanks
Sam
 
A

Anno Siegel

bsder said:
Yes I have added the kill() function in the signal_handler(), is this a
proper way to add kill() function in signal handler?

In which signal handler? That doesn't make sense. A signal handler is
activated when the process receives a signal. You want to *send* a
signal when the process exits, so call kill() when it exits.

If you want to automate the kill-on-exit, you could call the kill function
in an END block. Look up END in perlmod to see the possibilities and
limitations.

Anno
 
B

bsder

Anno said:
In which signal handler? That doesn't make sense. A signal handler is
activated when the process receives a signal. You want to *send* a
signal when the process exits, so call kill() when it exits.
have you look thru my server code? the signal handler is at the end of
the server code. I want to kill all its child processes when the server
code received an interrupt signal.

sam
 
A

Anno Siegel

bsder said:
have you look thru my server code?

No. You gave us 95 lines of code with no indication how it relates
to your question. I haven't read it.
the signal handler is at the end of
the server code. I want to kill all its child processes when the server
code received an interrupt signal.

That would kill the children only if the process itself is killed by
that specific signal. You can do that, but I'd still suggest taking
care of the children in an END block. You must still catch the signals
you expect to receive because an uncaught exception bypasses END. It
suffices to catch them unspecifically with "sub { die }".

Anno
 
B

bsder

Anno said:
No. You gave us 95 lines of code with no indication how it relates
to your question. I haven't read it.




That would kill the children only if the process itself is killed by
that specific signal. You can do that, but I'd still suggest taking
care of the children in an END block. You must still catch the signals
you expect to receive because an uncaught exception bypasses END. It
suffices to catch them unspecifically with "sub { die }".

Anno

I just want to follow C traditional style. There is no END style in C
anyway. well.. may be good just put kill() in the END block..

Thanks
Sam
 
A

Anno Siegel

bsder said:
[...]
[...]
That would kill the children only if the process itself is killed by
that specific signal. You can do that, but I'd still suggest taking
care of the children in an END block. You must still catch the signals
you expect to receive because an uncaught exception bypasses END. It
suffices to catch them unspecifically with "sub { die }".

Anno

I just want to follow C traditional style. There is no END style in C
anyway. well.. may be good just put kill() in the END block..

I took a look back at your code now you've said what part of it you
have problems with. One possible problem is that you set the signal
handler before you fork, so the kids have a (HUP-) handler too. It
looks to me that the kids should eventually die anyway, but it is
probably not what you want. Try setting the handler in the parent
only (after fork), or reset it in the kids.

For a Perl solution I'd still prefer END {}, but if you need a prototype
for a C(++) program, by all means debug the sig-handler solution. Is the
handler actually invoked? Does it succeed in sending the signal? What
is the return value of kill? Do the kids receive the signal? What
happens if you give an explicit list of pids instead of signalling the
process group?

Anno
 
B

Brian McCauley

bsder said:
Could anyone please tell me how to kill all child processes when parent
exit?

A neat trick on Unix is to open a FIFO before you fork and have the
child processes close the reading end (keeping open the writing end).

When the parent exists all the children get a SIGPIPE.

This, of course, has nothing to do with Perl - you can use this trick
in any language.
 
X

xhoster

bsder said:
Hi,

Could anyone please tell me how to kill all child processes when parent
exit?

elsif ($kidpid == 0) { # child
my ($cPort, $cHost) = unpack_sockaddr_in($addr);
my $cHostName = inet_ntoa($cHost);
print STDOUT "Client host: $cHostName\n";
print STDOUT "Client port: $cPort\n";
print NEWSOCK "Welcome to Code Generator.\r\n";

while (my $m=<NEWSOCK>) {
$m =~ s/\n|\r//g;
last if ($m eq ".");
print NEWSOCK "Server received $m\r\n";
}
close(NEWSOCK) || die "close in child: $!";
delete %kids->{$kidpid};
exit;

What is the point of the delete? For one thing, you've never put
anything into %kids, neither in parent nor child, so there is nothing to
delete. For another thing, you are immediately exiting, which mean %kids
is going away. Why change a variable which is going to disappear a
nanosecond later anyway? You probably want the delete to be in the
SIG{CHLD} handler, so that it occurs in the parent process rather than the
doomed child.

....
kill HUP => -$$;

In perl, you want to negate the signal, not the pid. But better yet,
once you fix your code dealing with %kids, kill them explicitly.

kill HUP => keys %kids.

Xho
 
B

Big and Blue

bsder said:
I just want to follow C traditional style. There is no END style in C
anyway.

Yes there is. It's called atexit(). (You might not have ever used it,
but that's another matter).

And what has C style got to do with programming in Perl anyway??? Do
you declare all variable to be ints/floats/char etc???
 

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

Similar Threads

length is 0 with unpack_socketaddr_in 1
Ensuring parent/child processes 8
Perl Sockets Parent/Child Problem 3
problem with IO:Socket 2
Telnet to cisco 3
Where's my STDOUT? 1
Fork Problem 2
Help with a program 0

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top