perl fork() exec() , child process gone wild
But when I do ctrl+c to kill the parent, the signal gets ignored by the child.
The signal is sent to two both the parent and the child.
$ perl -E'
if (my $pid = fork()) {
local $SIG{INT} = sub { say "Parent got SIGINT" };
sleep;
waitpid($pid, 0);
} else {
local $SIG{INT} = sub { say "Child got SIGINT" };
sleep;
}
'
^CParent got SIGINT
Child got SIGINT
If that child ignores it, it's because it started a new session or because it explicitly ignores it.
The child procces that runs the .sh script still STDOUT to the screen of the xterm. How can I remove this?
Do the following in the child before calling exec
:
open(STDOUT, '>', '/dev/null');
open(STDERR, '>', '/dev/null');
Actually, I would use open3
to get some error checking.
open(local *CHILD_STDIN, '<', '/dev/null') or die $!;
open(local *CHILD_STDOUT, '>', '/dev/null') or die $!;
my $pid = open3(
'<&CHILD_STDIN',
'>&CHILD_STDOUT',
'>&CHILD_STDOUT',
'shell.sh', 'args',
);
The parent process(perl script) doesn't wait on the child(.sh script). So I've read alot about the child becoming a zombie???
Children are automatically reaped when the parent exits, or if they exit after the parent exits.
$ perl -e'
for (1..3) {
exec(perl => (-e => 1)) if !fork;
}
sleep 1;
system("ps");
' ; ps
PID TTY TIME CMD
26683 pts/13 00:00:00 bash
26775 pts/13 00:00:00 perl
26776 pts/13 00:00:00 perl <defunct> <-- zombie
26777 pts/13 00:00:00 perl <defunct> <-- zombie
26778 pts/13 00:00:00 perl <defunct> <-- zombie
26779 pts/13 00:00:00 ps
PID TTY TIME CMD
26683 pts/13 00:00:00 bash
26780 pts/13 00:00:00 ps
<-- all gone
If the parent exits before the children do, there's no problem.
If the parent exits shortly after the children do, there's no problem.
If the parent exits a long time after the children do, you'll want to reap them. You could do that using wait
or waitpid
(possibly from a SIGCHLD
handler), or you could cause them to be automatically reaped using $SIG{CHLD} = 'IGNORE';
. See perlipc.
Perl Script, Fork/Exec, System claims my process has died when in fact only my child process has died
Just a sanity check, is your main program walking the right fork? It should follow the non-zero path:
my $pid = fork;
if ($pid == 0) {
print "Child\n";
} else {
print "Main\n";
}
From man fork:
Upon successful completion, fork()
returns a value of 0 to the child
process and returns the process ID of
the child process to the parent
process.
fork + exec + caller should not wait for child
Instead of using `` in script_a. We have redirected the STDOUT and STDERR in script_a.
Something like
script_a
system("script_b.pl > /var/tmp/out_file 2>&1");
script_b
#! /usr/local/bin/perl
$f_id = fork();
if (! $f_id) {
exec("sleep 10; echo 'i am child'");
}
if ($f_id) {
print "i am parent\n";
}
This way the caller didnot wait for the child in exec to complete.
Thanks for the help here.
Kill child process created with fork
When you fork a child, and then fail to wait() on it, it will become a defunct process (a zombie in Unix parlance) when it exits. You'll notice that its parent process ID becomes 1, and it will not go away until the OS rebooted.
So the traditional pseudocode for forking looks something like this:
if ($pid = fork()) {
# pid is non-zero, this is the parent
waitpid($pid) # tell OS that we care about the child
do other parental stuff
}
else {
# pid is 0 so this is the child process
do_childish_things()
}
Your code doesn't do that, so you're probably getting zombies, and then getting frustrated that you can't get rid of them.
how to kill process having multiple fork using perl
In a more complicated case, you can set the perl child process to be a session leader with POSIX::setsid()
, and then send the signal to the process group by passing a negative value to kill
.
if(!defined( my $pid = fork())) {
die "Cannot fork a child: $!";
} elsif ($pid == 0) {
POSIX::setsid(); # make this process a session leader
print "Printed by child process\n";
system("./program_that_forks"); exit; # or exec('./program_that_forks')
} else {
...
kill('KILL', -$pid); # -$pid means signal the whole process group
...
}
If the program_that_forks
is also manipulating process groups, either by calling setsid(1)
or by closing standard file descriptors and becoming a daemon, the convention is for the program to write its process id to a file, and for system task scripts to read this file to signal the program (run ls /var/run/*.pid
to see some examples).
Perl fork exec, system in parent and kill child
I figured that the problem was to kill the all process tree and
That SO answer solves the problem
I had this to the child process
setpgrp(0, 0);
And change the kill instruction to
kill 9, -$pid;
Looks like this now
my $pid = fork();
die "unable to fork: $!" unless defined($pid);
if (!$pid) { # child
setpgrp(0, 0);
exec("tail -f $logfile | logger -t $ENV{SUDO_USER}:$target ");
die "unable to exec: $!";
}
$show_cmd && print "% $cmd\n" ;
system $cmd or die "exec() failed: $!\n" ;
printf "Session end pid to kill %d\n", $pid;
kill 9, -$pid;
waitpid $pid, 0;
printf "End of the script.\n";
Thanks for helping me
Related Topics
How to Read Config Files with Section in Bash Shell
Process Stuck in Exit, Shows as Zombie But Cannot Be Reaped
Sending Keycode to Xorg + Wine with Bash Script
How to Capitalize First Letter of Each Line in Bash
Configure Options for Building Mingw-64 on Linux-64 for Linux-64 (Ultimately Targetting Windows-64)
Difference Between --Cap-Add=Net_Admin and Add Capabilities in .Yml
Bash Alias Create File with Current Timestamp in Filename
What Length Can a Network Interface Name Have
Limit Useable Host Resources in Docker Compose Without Swarm
How to Avoid "No Such File or Directory" Error for 'Make Clean' Makefile Target
Xkb: How to Convert a Keycode to Keysym
How to Access the Base Filename of a File You Are Sourcing in Bash
.Bashrc Syntax Error: Unexpected End of File
What Does the Line '!/Bin/Sh -E' Do
Changing Color of Eclipse Links in Quick Fix or Eclipse Links in Preferences on Linux
Bash: /Bin/Myscript: Permission Denied
Bash: How to Pass in Arguments to an Alias: Cannot Use a Function - Syntax of Bash Conditionals