fork, childs, zombies, start a process in the background without waiting for it

  • Thread starter Rex Gustavus Adolphus
  • Start date
R

Rex Gustavus Adolphus

Hi

I have a parent program, that should loop (eternally), and start other
programs without waiting for them, so many programs can be started at
the same time by the parent.

Is it true that it's not necessary to handle childsignals if you use
this type of logic when you fork processes:

if ($pid = fork) {
# parent
} elsif (defined $pid) {
# child
exec $agent
or die "Can't do $agent";
} else {
# fork error
die "can't fork\n";
}
 
R

Rex Gustavus Adolphus

: I have a parent program, that should loop (eternally), and start other
: programs without waiting for them, so many programs can be started at
: the same time by the parent.

Careful not to create a forkbomb. :)

: Is it true that it's not necessary to handle childsignals if you use
: this type of logic when you fork processes:
:
: if ($pid = fork) {
: # parent
: } elsif (defined $pid) {
: # child
: exec $agent
: or die "Can't do $agent";
: } else {
: # fork error
: die "can't fork\n";
: }

According to the perlipc manpage, it might even be easier, depending
on your surroundings:

On most Unix platforms, the CHLD (sometimes also known
as CLD) signal has special behavior with respect to a
value of 'IGNORE'. Setting $SIG{CHLD} to 'IGNORE' on
such a platform has the effect of not creating zombie
processes when the parent process fails to wait() on
its child processes (i.e. child processes are
automatically reaped). Calling wait() with $SIG{CHLD}
set to 'IGNORE' usually returns -1 on such platforms.

Greg

Thanks Greg!
But I'm sorry I don't understand if your answer means that the
fork-logic code I provided above is OK, so the parent doesn't have to
wait for the childs to avoid zombies?
Could you please clarify?
I like this to be as portable as possible so I'm a bit wary of the
'most' in 'On most Unix platforms...'
(On the Linux i tried, it said 'Can't ignore signal CHLD, forcing to
default.')

RGA
 
R

Rex Gustavus Adolphus

bob niederman said:
Not a fork-bomb because exec doesn't return.

W/ perl 5.8.0 on Linux (rh9.0) I couldn't seem to create zobies w/ exec.

With proccesses that ran perl and exited, I had zombies if I didn't
waitpid on them, but only while the parent was up - once the parent
finished, the zombie children went away too. YMMV on other perl/OS
combinations.

Thanks Bob,
but since my parent should keep running, I _must_ avoid leaving
zombies around.

I think I found the solution in PerlFAQ 8.12: "double fork"
(I must admit I thougt my previous method was "double fork" but I now
realize it isn't):
You immediately wait() for your first child, and the init daemon will
wait() for your grandchild once it exits.

unless ($pid = fork) {
unless (fork) {
exec "what you really wanna do";
die "exec failed!";
}
exit 0;
}
waitpid($pid,0);


BTW, whats "YMMV"?
/RGA
 
G

Greg Bacon

: Thanks Greg!

Glad to help.

: But I'm sorry I don't understand if your answer means that the
: fork-logic code I provided above is OK, so the parent doesn't have to
: wait for the childs to avoid zombies?
: Could you please clarify?

Assuming your platform exhibits that behavior, i.e., autoreaping
kids when you ignore SIGCHLD.

: I like this to be as portable as possible so I'm a bit wary of the
: 'most' in 'On most Unix platforms...'
: (On the Linux i tried, it said 'Can't ignore signal CHLD, forcing to
: default.')

If you want portability, good ol' double-fork is the way to go.

Greg
 
R

Rex Gustavus Adolphus

I think I found the solution in PerlFAQ 8.12: "double fork"
(I must admit I thougt my previous method was "double fork" but I now
realize it isn't):
You immediately wait() for your first child, and the init daemon will
wait() for your grandchild once it exits.

unless ($pid = fork) {
unless (fork) {
exec "what you really wanna do";
die "exec failed!";
}
exit 0;
}
waitpid($pid,0);

Hi, back again...

Now I tried double forking, and that seems to work in simple
testscripts,
but when I used it in my real app, witch involves DBI to connect
to an Oracle-database, my grandparent loses the db-connection as soon
as the grandparent spawns kids and grandkids (the grandkids connects
to the same database, but I'm not sending any db-handles to the kids
or anything like that).

(I have not yet been able to figure out at what exact moment the
grandparent loses it's db-connection)

I quote from "Programming Perl": "File descriptors ... are shared,
while everything else is copied--or at least made to look that way."

What does this mean?

If I have:
my $dbh = ${&db_connect()};
in the forking program
is $dbh copied to the kids and therefore dropped when the kids dies?




Anyway, now I'm trying this method instead, it seems to work:

# found something to do:
system("what I really wanna do &"); # NB the '&' at the end

# I can keep on immediately, because of the '&' above
# doing more system-calls if needed


Simple!
No forking, no waiting, no zombies, no hassles!

Why didn't I do this from the beginning?


Is there any disadvantage?
Anything I'm missing?

/RGA
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top