Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Killing child processes without waiting for the child to finish

Posted on 2006-11-06
9
743 Views
Last Modified: 2012-06-21
Code is roughly:

open(FILE, "+<file");
flock (FILE,2);
#read data from the file
spawn_child();
#write to the file
close (FILE);

sub REAPER {
   my $wait_pid = wait;
}

sub spawn_child() {
   $SIG{CHLD} = \&REAPER;
   my $pid = fork();
   if (!$pid) {
      exec ("perl script");
      exit; #redundant, I know
   }
   return;
}

The issue is that "script" contains an open to "file", which is currently locked by the parent process. I can't change the order of the main logic (i.e. can't write to the file before I spawn the child). The way it's written now, the parent seems to be waiting for the child to finish executing before it continues on with the logic, creating a deadlock (child is waiting for "file" to be unlocked, parent is waiting for child to finish before unlocking "file"). I need the parent to continue on without the child finishing (the parent also needs to continue to spawn children while the child processes run their course, so waiting for each child to finish is unacceptable).

I've tried running the child as a background process, but this seems to cause "script" to never come out of sleep() commands (/boggle). Any other suggestions?
0
Comment
Question by:Asdf
9 Comments
 
LVL 39

Expert Comment

by:Adam314
ID: 17885087
what are you trying to do?  (high-level)
0
 
LVL 84

Accepted Solution

by:
ozo earned 63 total points
ID: 17885328
flock (FILE,2);
#read data from the file
flock(FILE,8);
spawn_child();
flock (FILE,2);
#write to the file
close (FILE);
0
 

Author Comment

by:Asdf
ID: 17889389
Adam314:

Parent spawns X children, running simultaneously. Child and parent communicate through a "status" file. When the child finishes, parent will read that status and spawn a new child.

ozo's solution does solve the file locking deadlock, but the parent still waits for the child to finish executing before moving forward in the logic, meaning I can only have a single child running at once.

What if the child never died on it's own, and it was up to the parent to kill the child when the child set it's status to "done"? As of now, we'd be stuck because the would wait for the child to die indefinitely. How can I make the parent stop waiting for the child to finish, but still reap the child (it's necessary to reap the child because cygwin only allows 256 children from a single process, and I need to exceed this number in my use case)?
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 

Author Comment

by:Asdf
ID: 17890468
Another point of interest:

Speckled throughout my code I have various qx!echo "something" >> log.txt!; lines, mostly for debugging purposes. It seems that the parent is "freezing" when it finishes executing the first qx! after the fork(). I'm thinking these qx!'s are the issue, not my method of reaping. I tested this with some basic sample code and saw the same thing:

foreach my $num (1..3) {
   open (T, ">>txt");
   flock (T, 8);
   &spawn();
   flock (T, 2);
   print T "$num parent\n";
   close (T);
}

sub REAPER {
   my $var = ("process died: ",wait);
}

sub spawn {
   $SIG{CHLD} = \&REAPER;
   my $pid = fork();
   if (!$pid) {
      exec ("perl sleeper");
   }
   qx!ls!;
}

the code in sleeper:

sleep(4);
open (T, ">>txt");
flock (T, 2);
print T "sleeper\n";

Resulting "txt":
sleeper
1 parent
sleeper
2 parent
sleeper
3 parent

If you comment out the qx!, the result is:
1 parent
2 parent
3 parent
sleeper
sleeper
sleeper

Is this expected behavior? If so, why, and is there a way around it?
0
 
LVL 11

Expert Comment

by:kblack05
ID: 17911133
I believe adding the line

next;

to the parent codeblock where it is to pass over the child should work.
0
 
LVL 11

Assisted Solution

by:kblack05
kblack05 earned 62 total points
ID: 17911135
Also try using this method to trap your errors

To obtain useful error messages, add the following snippet to your script, just beneath the shebang line (the first line of the script; usually !#/usr/local/bin/perl or !#/usr/bin/perl):

BEGIN {
open (STDERR, ">/path/to/somewhere/error.txt");
}

0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question