Fork, exec - setsid?

R

Robert Manea

Hello everyone,

I'm trying to solve a quite simply looking job but can't really come up
with an elegant working solution.


The why:
--------

I wrote a frontend to a DVB (digital video broadcasting) card in
Gtk2 using Perl. So I came up with the need to fork some processes away
and execute a couple of external programs via 'exec()'; these programs
are linked together via pipes.

The DVB-card is built in a remote machine so I first have to fork away a
new process and do:

exec('ssh remote-machine start-the-dvb-stuff-and-multicast-it')

after that fork away another process and:

exec('grab-the-stream | demultiplex-it | videoplayer').


The problem:
------------

As exec normally never returns and spwans a shell when it finds any
metachars in the command to be executed there is no means to get the PID
of those or the spawned shell.

But unfortunatelly I have to quit those processes every time the user
wants to switch channels via the parent.


The question:
-------------

How do I kill the forked away programms without knowing their PID?
Or better, how to kill them based on their SID?


What I tried:
-------------

(the commands where replaced by some simpler ones to make testing
easier)

#v+
#!/usr/bin/perl
#
use strict;
use warnings;
use POSIX;

$SIG{'CHLD'} = \&reaper;

sub reaper {
$SIG{'CHLD'} = \&reaper;
#my $kid = waitpid(-1, WNOHANG);
my $kid = wait();
}

my $command='tail -f foo|grep grep';

my $cpid = fork();
if ( $cpid == 0) {
print "Child starting\n";
my $s_id = POSIX::setsid(); # Put the stuff into an own session
exec $command;
} elsif ($cpid < 0) {
warn "Cannot fork: $!";
}

sleep 5; # Actually the parent runs forever

kill 9, $cpid;

sleep 5;
return ;

__END__
#v-

This doesn't seem to work as the 'exec()'ed commands exist further on
after killing the child process.


The work around:
----------------

Simply remember the 'exec()'ed command names and do a
system('pkill -9 grab-the-stream') and so on..

This looks more than ugly and I'm sure there are way nicer methods.


Greets & TIA, Rob
 
A

Anno Siegel

Robert Manea said:
Hello everyone,

I'm trying to solve a quite simply looking job but can't really come up
with an elegant working solution.


The why:
--------

I wrote a frontend to a DVB (digital video broadcasting) card in
Gtk2 using Perl. So I came up with the need to fork some processes away
and execute a couple of external programs via 'exec()'; these programs
are linked together via pipes.

The DVB-card is built in a remote machine so I first have to fork away a
new process and do:

exec('ssh remote-machine start-the-dvb-stuff-and-multicast-it')

after that fork away another process and:

exec('grab-the-stream | demultiplex-it | videoplayer').


The problem:
------------

As exec normally never returns and spwans a shell when it finds any
metachars in the command to be executed there is no means to get the PID
of those or the spawned shell.

The shell will have the pid that fork() returned to the parent.
But unfortunatelly I have to quit those processes every time the user
wants to switch channels via the parent.


The question:

Kill the shell that runs the pipeline. You have the pid.

Anno
 
R

Robert Manea

Segfault in module "Anno Siegel" - dump details are as follows:
Kill the shell that runs the pipeline. You have the pid.


Unfortunatelly this won't do the job. After killing the shell (in other
words the PID returned by 'fork()') the programms in the pipeline still
exist and are up and running.

This strategy was what I tried first..

Greets, Rob
 
A

Arndt Jonasson

Robert Manea said:
#!/usr/bin/perl
#
use strict;
use warnings;
use POSIX;

$SIG{'CHLD'} = \&reaper;

sub reaper {
$SIG{'CHLD'} = \&reaper;
#my $kid = waitpid(-1, WNOHANG);
my $kid = wait();
}

my $command='tail -f foo|grep grep';

my $cpid = fork();
if ( $cpid == 0) {
print "Child starting\n";
my $s_id = POSIX::setsid(); # Put the stuff into an own session
exec $command;
} elsif ($cpid < 0) {
warn "Cannot fork: $!";
}

sleep 5; # Actually the parent runs forever

kill 9, $cpid;

sleep 5;
return ;

__END__
#v-

This doesn't seem to work as the 'exec()'ed commands exist further on
after killing the child process.

'kill' can take a negative number, and then kills the processes in a
process group. This may be what you want. Thus:

kill 9, -$cpid;

Another solution is to send $s_id up to the parent by some means.
 
A

Anno Siegel

Robert Manea said:
Segfault in module "Anno Siegel" - dump details are as follows:




Unfortunatelly this won't do the job. After killing the shell (in other
words the PID returned by 'fork()') the programms in the pipeline still
exist and are up and running.

This strategy was what I tried first..

That would mean that one or another of the programs you start has
demon-like properties and puts itself in the background (It may leave
a pidfile around, if so).

The whole thing has little to do with Perl, but is a fork/exec/kill
issue and also depends on the behavior of the programs you run. The
question to ask is, how would you end a run if the program was used
"normally", whatever that means, and see how to gain that kind of
control from Perl.

Anno
 
R

Robert Manea

Segfault in module "Anno Siegel" - dump details are as follows:
That would mean that one or another of the programs you start has
demon-like properties and puts itself in the background (It may leave
a pidfile around, if so).

Well, if I understand the documentation correctly I have to contradict
you.

A shell with job control arranges a pipeline in such a way that the
invoking instance of the shell is the process group leader (PGL).

A process group (PG) will be exsisting until all of the processes in
this group have been terminated even if the PGL has been killed.

Thus there is no need for any process within the PG to be daemonized in
order to exist after the PGL has been terminated.

Or am I misinterpreting something?
The whole thing has little to do with Perl, but is a fork/exec/kill
issue and also depends on the behavior of the programs you run. The
question to ask is, how would you end a run if the program was used
"normally", whatever that means, and see how to gain that kind of
control from Perl.

Ok, agreed. Not a 100% pure perl thing. Should have better asked in a
unix.programmer group..

Maybe a F'UP?

Greets, Rob
 
A

Anno Siegel

Robert Manea said:
Segfault in module "Anno Siegel" - dump details are as follows:


Well, if I understand the documentation correctly I have to contradict
you.

You're right. A pipeline can survive the shell that started it.

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

Similar Threads

Fork (and exec) in a threaded script. 4
Fork Problem 2
fork it 11
PID of exec 0
Marc the Reaper 9
PID of exec 34
sleep/fork/shell/SIGCHLD interaction problem 8
waitpid woes on Solaris, Perl 5.8.8 7

Members online

No members online now.

Forum statistics

Threads
473,930
Messages
2,570,072
Members
46,521
Latest member
JamieCooch

Latest Threads

Top