Re: getting a child's process ID
by davorg (Chancellor) on Oct 19, 2001 at 19:19 UTC
|
Well, backtick and system don't return until
the child process has finished, so its PID would be of no
use. exec replaces your process with the child
process, so again you won't be able to use the PID as your
program will no longer be running.
fork returns the PID of the child to the parent
and 0 to the child so that you can tell the difference
between the two processes.
--
<http://www.dave.org.uk>
"The first rule of Perl club is you don't talk about
Perl club."
| [reply] |
|
|
I tried using fork(), it returns the PID of the fork, but not the process within the fork, that's what I want to exit. This is what I have:
#!/usr/bin/perl -w
use POSIX;
if ($pid = fork)
{
# parent
open(OUT,">Test.txt");
print OUT "The process: $pid\n";
close(OUT);
}
else
{
# child
exec("emulator.exe");
exit(0);
}
the pid that is printed in the file is not that of the exec() call, that's what I'm interested in getting so that I can quit it.
| [reply] [d/l] |
|
|
#!/usr/bin/perl -w
# parent.pl
use strict;
if (my $pid = fork) {
print "parent: child pid is $pid\n";
} else {
exec('./child.pl');
}
#!/usr/bin/perl -w
# child.pl
use strict;
print "Child: pid is $$\n";
And the output I got was:
parent: child pid is 26534
Child: pid is 26534
--
<http://www.dave.org.uk>
"The first rule of Perl club is you don't talk about
Perl club."
| [reply] [d/l] [select] |
|
|
|
|
Seshouan, I just re-read the posts in this thread again, and enlightenment struck me like a ton of bricks (I think ;) Are you using ActivePerl on Windows? Because in that version of perl, process ID's don't stay the same across an exec() call. The PID is supposed to stay the same, and on Unix, it does; that's why davorg's example works and yours doesn't -- he tried his on Unix.
The problem is, Win32 doesn't have a way to launch a new program without changing the PID. On Unix, exec() is an actual system call that loads a new program into a pre-existing process. On Win32, exec() is implemented by having the exec-ing process call CreateProcess, and then exit. So on Unix the $pid=fork trick works because the program you are exec-ing ends up in the child you created with fork, but on Windows, the program you exec ends up as a grandchild of the original process. Oops. That will make things a lot harder.
I can think of two ways to solve this problem: (1) use Cygwin's Win32 perl instead of ActivePerl, or (2) hack together some kind of inter-process communication to let the parent process find out the child's pid. For example, pass the child a command-line argument that's a filename where it can write its pid once it starts up. Unfortunately, both these solutions require that you're in control of both the exec'd child and the parent. If not, there's probably still something you can do to get the child's pid, but I can't think of it off the top of my head. And of course all of this is irrelevant if you're not actually running on Win32. Anyway, good luck.
| [reply] |
Re: getting a child's process ID
by blackmateria (Chaplain) on Oct 19, 2001 at 19:16 UTC
|
If you're on *nix, fork() returns the child's pid to the parent, and 0 to the child. This works on Cygwin's Win32 port as well (not sure about ActivePerl).
Update: Looks like it works on ActivePerl, too (at least build 613+). | [reply] |
Re: getting a child's process ID
by aijin (Monk) on Oct 19, 2001 at 19:19 UTC
|
I think what you're looking for is fork.
-aijin | [reply] |
Re: getting a child's process ID
by jlongino (Parson) on Oct 19, 2001 at 20:47 UTC
|
I was wondering and maybe someone that replied earlier to
this thread can tell me. Is there some way that the child
can determine whether or not the parent process is still
running (Active State Perl 5.6.x)? I'm familiar with doing
this in a xnix environment with getppid
but I know it's not available under ASP. I believe Seshouan
was looking for similar information in a post yesterday as well.
Thanks,
--Jim
| [reply] |
|
|
Remember that at some point of the child's lifetime, it was the parent. Just do something along the lines of:
#!/usr/bin/perl -w
use strict;
our $Parent_PID = $$;
# ... Many interesting lines of code ...
my $pid;
# The mini-loop below will re-attempt the fork()
# in case of errors, that are usually transient
# resource shortages. You might not want to do this
# in your scenario...
while (($pid = fork()) < 0) { sleep 5; }
if ($pid) { # Father
print "father: the child is $pid\n";
# ... Interesting code to wait for the children ...
}
else { # Child
print "child: My parent is $Parent_PID\n";
print "child: I am $pid (or $$)\n";
}
Hope this helps you. | [reply] [d/l] |
|
|
jlongino -- much to my chagrin when working on Windows, Win32 doesn't have a (portable) getppid() equivalent. The closest equivalent is the Process32*() functions in the toolhelp library--these have a way of getting the parent pid. Unfortunately, they don't work on WinNT 4.0. Also, ActivePerl doesn't appear to use toolhelp (at least, a quick "grep -ir process32 *" from the root of my ActivePerl build 613 install didn't turn up anything). There might be a CPAN module that talks to toolhelp, I'm not sure. In any case, it's not portable.
I'd say your best bet is to either use some form of inter-process communication (if you have control of the parent process), or else use the Cygwin version of perl instead of ActiveState if you can. getppid() works in that version. Also, beware of ActiveState's fork() -- it doesn't play very well with their implementation of sockets. I usually end up either using Cygwin or, for C programs, writing IPC code. Hope this helps!
| [reply] |
|
|
| [reply] |
Re: getting a child's process ID
by markdibley (Sexton) on Jan 09, 2015 at 13:11 UTC
|
Sorry to revive this, but I have a problem with the way my code is working and it is related to this issue.
I am using the same if...fork...else...exec process as @davorg but when I look at the ps -ef output I find 2 processes.
if(my $pid = fork()){
$this->set_pid_in_db($id, $pid);
}
# Child process starts service and inherits child PID
else{
my $command = sprintf("%s %s 1>>%s 2>>%s", $this->fnClient(), $id,
+ $this->fnOe($id), $this->fnOe($id));
#my $command = sprintf("%s %s", $this->fnClient(), $id);
exec($command);
}
>ps -ef | grep SB
mark 11970 1 0 07:57 pts/1 00:00:00 sh -c /code/SBClient2.pl j
+ob1 1>>/log/log.1.oe 2>>/log/log.1.oe
mark 11971 11970 77 07:57 pts/1 00:00:06 /usr/bin/perl /code/SBClie
+nt2.pl job1
And the PID that was set on line 2 is 11970 rather than 11971. Of course, I can still test to see if 11970 is running and that will tell me if 11971 is running. And I can kill 11970 and that will kill 11971.
However, what confuses me is that if I don't redirect output and error to a file (i.e. use the commented out command instead), then 1 process rather than 2 processes are started.
Does anyone know why this happens? | [reply] [d/l] |
|
|
If Perl finds something in the command line for exec or system that it can't interpret (like a redirection), it will invoke the shell to parse the command. This is what's happening here.
As a solution, you could either do the redirect yourself by reopening STDERR to the file or restructure your approach so that you get the correct PID into the appropriate place.
| [reply] |
|
|
Thanks for the reply. The idea is to make this code independent of what it is running. It seems every day my argument for using perl gets weaker and weaker.
| [reply] |
|
|