Re: How to get a pid

2006-08-02 Thread wren ng thornton
--- quoth Ted Zeng [EMAIL PROTECTED]:
 Originally, my perl script launches Eggplant as a
 child process (use ``, not an independent process.)

Actually ``, aka qx(), does spawn an independant
process. Try running:

perl -e'`sleep 6000`;' 

and then doing a `ps` to see. But the semantics of
qx() mean that the forking, execing, and capturing of
output are hidden from the programmer. Same goes for
using system().

Because of the semantics of qx() and system(), there's
no way to capture the pid of the spawned process--
that's all handled behind the scenes. If you don't
trust the children to return properly, then you need
to use fork() and exec() explicitly with something
like the following:

#!/usr/bin/env perl
print $$: noone in here but us chickens\n;
$pid = fork();
print $$: I got $pid\n;
if ($pid == 0) {
print $$: child is execing\n;
exec 'sleep', 10;
} else {
print $$: parent is waiting\n;
sleep 5;
print $$: kids these days! (killing $pid)\n;
kill 9, $pid;
}
__END__

You can watch this in another shell with a ps. You can
also use elements of %SIG for the first argument to
kill() but `sleep` so happens to ignore everything. Do
note that the interleaving of the process scheduling
after calling fork() is unpredictable, even if it
appears reliable over a few runs. Even the order in
which processes return from a call to fork() is
unpredictable.

Unfortunately with this approach, capturing the output
of the child is harder. And of course you'll want to
verify that the child is running too long before
killing it in your version.

Live well,
~wren

__
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 


Re: How to get a pid

2006-08-02 Thread Ted Zeng
Hi wren,

Thanks. I know better now.
I will try to fix the problem within my time limit.

Best wishes,

Ted zeng



On 8/2/06 1:18 AM, wren ng thornton [EMAIL PROTECTED] wrote:

 --- quoth Ted Zeng [EMAIL PROTECTED]:
 Originally, my perl script launches Eggplant as a
 child process (use ``, not an independent process.)
 
 Actually ``, aka qx(), does spawn an independant
 process. Try running:
 
 perl -e'`sleep 6000`;' 
 
 and then doing a `ps` to see. But the semantics of
 qx() mean that the forking, execing, and capturing of
 output are hidden from the programmer. Same goes for
 using system().
 
 Because of the semantics of qx() and system(), there's
 no way to capture the pid of the spawned process--
 that's all handled behind the scenes. If you don't
 trust the children to return properly, then you need
 to use fork() and exec() explicitly with something
 like the following:
 
 #!/usr/bin/env perl
 print $$: noone in here but us chickens\n;
 $pid = fork();
 print $$: I got $pid\n;
 if ($pid == 0) {
 print $$: child is execing\n;
 exec 'sleep', 10;
 } else {
 print $$: parent is waiting\n;
 sleep 5;
 print $$: kids these days! (killing $pid)\n;
 kill 9, $pid;
 }
 __END__
 
 You can watch this in another shell with a ps. You can
 also use elements of %SIG for the first argument to
 kill() but `sleep` so happens to ignore everything. Do
 note that the interleaving of the process scheduling
 after calling fork() is unpredictable, even if it
 appears reliable over a few runs. Even the order in
 which processes return from a call to fork() is
 unpredictable.
 
 Unfortunately with this approach, capturing the output
 of the child is harder. And of course you'll want to
 verify that the child is running too long before
 killing it in your version.
 
 Live well,
 ~wren
 
 __
 Do You Yahoo!?
 Tired of spam?  Yahoo! Mail has the best spam protection around
 http://mail.yahoo.com 



Re: How to get a pid

2006-08-02 Thread Joel Rees
One way of seeing that the grandfather process can terminate  
grandchild processes is to have the child process catch the signal  
and kill, in turn, its own child processes, as part of its clean-up  
code before it dies. This means that you have to use a signal that  
can be recovered from when killing the child process.


Re: How to get a pid

2006-08-01 Thread Ted Zeng
Thanks. This is a pretty good lecture on OS's process.

You are right. The problem is the Grandchild could not be trusted.
And the child is stuck with the grandchild due to the way it launches
The grandchild.

But since the parent knows child's pid, it could use this information
To  find out the grandchild's pid (as Packy proposed). I think that solves
The problem pretty well.

Ted Zeng
Adobe Systems Inc.


On 7/31/06 6:06 PM, wren ng thornton [EMAIL PROTECTED] wrote:

 --- quoth Packy Anderson:
 --- quoth Ted Zeng:
 I don't know how the OS generate the pid for a
 process. That is why I don't
 feel comfortable with what I did.
 
 The way I understand it, the OS assigns the next
 highest available pid when creating a process.
 
 It' s never specifically documented because it's one
 of those implementation dependent things, but
 canonically speaking it's the next available pid
 which is either a first fit or next fit depending on
 which is easier to implement.
 
 Due to the nature of the lifecycles of processes this
 generally means that in practice child=ppid+1 but in
 actuality there is no guarantee that the two pids are
 related to one another. This general observation can
 be undone by wrapping of pids past the max pid, by
 some other process jumping in to spawn a child before
 your process' request is fulfilled, by other processes
 dying off and revealing a better next available pid,
 etc etc.
 
 Whenever a process makes a syscall to fork() an exact
 copy of the current process is made (including all
 open files and some other complexities), with the only
 difference being the pid. The other difference is that
 once the call to fork() returns the parent will
 receive the child's pid as a return value and the
 child will receive 0 (an invalid pid). If for for some
 reason the fork fails (e.g. no available pids), then
 the parent process will receive -1 (also an invalid
 pid).
 
 Generally it's up to the parent to keep track of their
 children and there's not much recourse to recovering
 them if you loose them. However the OS does keep track
 of such things (to deal with auto-reaping zombies and
 the like) and so there're often ways to recover that
 info. E.g. in C the waitpid() function has an option
 to wait for any child to die; I don't know of a Perl
 implementation if this call, but I wouldn't be
 surprised if it's out there, and if it isn't anyone
 with a bit of XS knowledge should be able to bang one
 out quickly. There may be other ways depending on the
 specific OS.
 
 I've only loosely been following this thread, but it
 sounds like the problem isn't the parent (the Perl
 script) keeping track of it's children, but rather
 keeping track of grandchildren. Since POSIX makes no
 province for keeping track of grandchildren, it's
 really something the child should keep track of and
 then report to the parent. That is, every process
 should clean up after themselves and so every parent
 can consider their child to be one process ignoring
 any other processes they may spin off. Of course it
 sounds like the child is an unknown (and not
 particularly trusted). Is there not any way for the
 Perl script to call the necessary grandchildren
 directly?
 
 Live well,
 ~wren
 
 __
 Do You Yahoo!?
 Tired of spam?  Yahoo! Mail has the best spam protection around
 http://mail.yahoo.com 



Re: How to get a pid

2006-07-31 Thread Ted Zeng
I don't know how the OS generate the pid for a process. That is why I don't
feel comfortable with what I did.

I am not sure if there is a race situation here.

Ted zeng


On 7/28/06 4:21 PM, Joel Rees [EMAIL PROTECTED] wrote:

 
 On 2006/07/29, at 4:12, Ted Zeng wrote:
 
 ...
 
 I have used  pid+1 for quite a few days now and it seems to work
 without any problem. But I still feel it is not the right thing to do.
 
 Have you ever heard of race?



Re: How to get a pid

2006-07-31 Thread Packy Anderson

On Jul 31, 2006, at 5:35 PM, Ted Zeng wrote:
I don't know how the OS generate the pid for a process. That is why  
I don't

feel comfortable with what I did.


The way I understand it, the OS assigns the next highest available  
pid when
creating a process.  However, pids wrap around when they reach the  
maximum

defined pid.  So, if your process' pid is near the max, your child could
get a lower pid.

What you want to do is find the pid of your child's child.  There's  
probably
a system call you can make to find these things, but I don't know it.  
What
I do know is how to use ps -j or ps -l.  I've whipped up the  
following

script to demonstrate the technique.

Note: the script you're waiting on may have spawned off children of  
it's own,
so it'd be a good idea to find them and kill them first.  This, of  
course,

may let the script spawn off even more processes...

 start demo script 
#!/usr/bin/perl

use POSIX qw(:sys_wait_h);  # need this to get non-blocking waitchild

$|=1; # autoflush on

unless (defined($kid_pid = fork())) {
die Cannot fork: $!;
}

if ($kid_pid == 0) {
# we're running as the child process
execNightshade();
}
else {
print Watching child $kid_pid...\n;
my $count=0;
my $tConstant = 1; ## I'm impatient
do {
print Sleeping ... ;
sleep 10;
$count++;
$kid = waitpid($kid_pid, WNOHANG);
print kid: $kid_pid, waitpid: $kid\n;
} until ($kid  0 or $count  $tConstant);

if ($count  $tConstant ) {
recursive_kill($kid_pid);
}
}

sub execNightshade {
# since we don't know what execEggplant does beside exec-ing shell
# scripts with ``, let's make something up...

my $count = join q{ }, 1 .. 10; # make a string '1 2 3 4 5 6 7 8  
9 10'


# this shell script prints numbers from 1 to 100, sleeping 10
# seconds between each number...
my $output = `for i in $count; do echo \$i; sleep 10; done`;

# what good is output if we don't use it?
print $output\n;
}

sub recursive_kill {
my($pid) = @_;

while (my $child = child_pid($pid)) {
# kill all its children, grandchildren, etc...
recursive_kill($child);
}

# then kill the process itself
print Killing $pid\n;
kill 9, $pid;
}

sub child_pid {
my($parent) = @_;

# we want to know the process id of the child that's been forked
# by our own child.  since OS X is a unix, we can use ps to find
# it.  the following highly non-portable code should work on OS X
# and _maybe_ some other unices, but definately won't work on
# WinAnything or other, stranger OSes...

my $grandkid_pid;
open my $ps, ps -l |;
while ($ps) {
# unless the first field is numeric, we're looking at the
# column headings.  let's discard it.
next unless /^ \s* \d+ /msx;

# split /PATTERN/,EXPR,LIMIT
#
# If EXPR is omitted, splits the $_ string.  If PATTERN is
# also omitted, splits on whitespace (after skipping any
# leading whitespace).
#
# As a special case, specifying a PATTERN of space (' ')
# will split on white space just as split with no
# arguments does.

my($uid, $pid, $ppid, $other_fields) = split q{ }, $_, 4;

# if the process' parent pid isn't our kid's pid, we're
# not interested in it
next unless ($ppid == $parent);

# congratulations!  you're a parent!
return $pid;
}
return; # if there's no child, just return
}
 end demo script 

Sample output:
$ pid_test.pl
Watching child 7718...
Sleeping ... kid: 7718, waitpid: 0
Sleeping ... kid: 7718, waitpid: 0
Killing 7724
Killing 7729
Killing 7733
Killing 7736
Killing 7739
Killing 7742
Killing 7745
Killing 7748
Killing 7751
1
2
3
4
5
6
7
8
9
10

Killing 7719
Killing 7718
$

What's happening is the script is killing the 'sleep', and then before
the subroutine can return and kill off the for loop, it's sleeping  
again.

Fortunately, it disposes of the sleeps fairly quickly, and the child
process actually returns its data before it gets killed.

--
Packy Anderson   
[EMAIL PROTECTED]


Catapultam habeo. Nisi pecuniam omnem mihi dabis, ad caput tuum saxum
immane mittam.




Re: How to get a pid

2006-07-31 Thread wren ng thornton
--- quoth Packy Anderson:
 --- quoth Ted Zeng:
  I don't know how the OS generate the pid for a
  process. That is why I don't
  feel comfortable with what I did.
 
 The way I understand it, the OS assigns the next
 highest available pid when creating a process.

It' s never specifically documented because it's one
of those implementation dependent things, but
canonically speaking it's the next available pid
which is either a first fit or next fit depending on
which is easier to implement.

Due to the nature of the lifecycles of processes this
generally means that in practice child=ppid+1 but in
actuality there is no guarantee that the two pids are
related to one another. This general observation can
be undone by wrapping of pids past the max pid, by
some other process jumping in to spawn a child before
your process' request is fulfilled, by other processes
dying off and revealing a better next available pid,
etc etc.

Whenever a process makes a syscall to fork() an exact
copy of the current process is made (including all
open files and some other complexities), with the only
difference being the pid. The other difference is that
once the call to fork() returns the parent will
receive the child's pid as a return value and the
child will receive 0 (an invalid pid). If for for some
reason the fork fails (e.g. no available pids), then
the parent process will receive -1 (also an invalid
pid).

Generally it's up to the parent to keep track of their
children and there's not much recourse to recovering
them if you loose them. However the OS does keep track
of such things (to deal with auto-reaping zombies and
the like) and so there're often ways to recover that
info. E.g. in C the waitpid() function has an option
to wait for any child to die; I don't know of a Perl
implementation if this call, but I wouldn't be
surprised if it's out there, and if it isn't anyone
with a bit of XS knowledge should be able to bang one
out quickly. There may be other ways depending on the
specific OS.

I've only loosely been following this thread, but it
sounds like the problem isn't the parent (the Perl
script) keeping track of it's children, but rather
keeping track of grandchildren. Since POSIX makes no
province for keeping track of grandchildren, it's
really something the child should keep track of and
then report to the parent. That is, every process
should clean up after themselves and so every parent
can consider their child to be one process ignoring
any other processes they may spin off. Of course it
sounds like the child is an unknown (and not
particularly trusted). Is there not any way for the
Perl script to call the necessary grandchildren
directly?

Live well,
~wren

__
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 


Re: How to get a pid

2006-07-29 Thread Peter N Lewis

I could not figure out how to get the tool process's id. But by observing,
I notice that its pid is 'always' equals to child process's pid+1.


PIDs can wrap, so there is no guarantee of this at all.

Why do you call waitpid with -1, when you know the pid you want to 
wait on ($kidpid).


The reason for zombies (ie, (perl)) is normally that the process 
has died, but no one has requested the termination status (with 
waidpid or its cousins).


I admit to having no idea what execEggplant does.  But it sounds like 
it is running another subprocess.  Really, it needs to wait on that 
sub process and return when it is complete.


You could use killall to find the process by name:

killall -s -d Preview

although that is always a bit risky if the process name is not known 
and unique.


Otherwise you have problems.
   Peter.

--
Check out Interarchy 8.1.1, just released, now with Amazon S3 support.
http://www.stairways.com/  http://download.stairways.com/


RE: How to get a pid

2006-07-28 Thread Ted Zeng


It would have been helpful to see the contents of execEggplant.  Is it really
using exec?  If so, the child's pid should be the same as the thing that exec'd
it.
 Sorry. I should be more clear. My code uses `   ` (backward qoute?),  which 
 is the same as system(), I think.  So it is not exec(), open().
execEggplant is a command that executes eggplant with a Eggplant script path as 
parameter. 
I also pipe the error to output.

$execEggplant = runscript an_eggplant_script_path 2$1   ## just from my 
memory. I don't have the script on hand right now.

The reason I doesn't use exec is because I want to catch the output from 
Eggplant (it write its log to err).
If I use exec(), then I wouldn't be able to see the output from that process.

I have no experience with open() and took a look at it, and it doesn't seem to 
work for my case.

I have used  pid+1 for quite a few days now and it seems to work without any 
problem. But I still feel it is not the right thing to do.

ted


If you use open(), the return value of open will be the pid of the pipe opened.

If you use system(), you may be out of luck; I don't know.

...or is it the case that execEggplant exec's some script which then, itself
runs Eggplant?  In that case, you will have to roll your own IPC.

-- 
rjbs



Re: How to get a pid

2006-07-28 Thread Joel Rees


On 2006/07/29, at 4:12, Ted Zeng wrote:


...

I have used  pid+1 for quite a few days now and it seems to work  
without any problem. But I still feel it is not the right thing to do.


Have you ever heard of race?


Re: How to get a pid

2006-07-27 Thread Ricardo SIGNES
* Ted Zeng [EMAIL PROTECTED] [2006-07-25T13:17:13]
 I could not figure out how to get the tool process's id. But by observing,
 I notice that its pid is 'always' equals to child process's pid+1.

It would have been helpful to see the contents of execEggplant.  Is it really
using exec?  If so, the child's pid should be the same as the thing that exec'd
it.

If you use open(), the return value of open will be the pid of the pipe opened.

If you use system(), you may be out of luck; I don't know.

...or is it the case that execEggplant exec's some script which then, itself
runs Eggplant?  In that case, you will have to roll your own IPC.

-- 
rjbs


signature.asc
Description: Digital signature


How to get a pid

2006-07-25 Thread Ted Zeng
Hi,

I have the following problem.

I run a perl script that set up an environment, then
Run a tool and wait for its return.

But the tool hangs from time to time. I have to kill it when it hangs.

To do  this, I use Fork. I fork a child process that will run the  tool.
In the parent process, I get the child process's pid and if it runs longer
than a set time limit, the parent will kill the child.

But I found out that while the child dies, it still hangs around with the
tool. (it has (perl) when I do 'ps -xc' ).

If I kill the tool process, then thing is ok.

I could not figure out how to get the tool process's id. But by observing,
I notice that its pid is 'always' equals to child process's pid+1.

So, I let the parent process kills 'child pid+1. It seems to work so far.

I have to admit I don't feel comfortable with doing this, though it works so
far.

Any suggestion on how I could figure out the tool's pid?

Regards,

Ted Zeng
Adobe Systems Inc.

Here is the part of the script that does fork:

if(!defined( $kidpid = fork() )){
die Canot fork: $!;
}elsif ($kidpid == 0) {
## Execute the Eggplant Scripts.
execEggplant();
} else {
my $count=0;
my $tConstant = 120; ## 20 min.
do {
sleep 10;
$count ++;
$kid = waitpid(-1, WNOHANG);
} until ($kid  0 or $count  $tConstant);
if($count  $tConstant ){
{
$kidpid = $kidpid + 1; ## get the Eggplant PID
## The child process is still running. Log and kill it.
my $ret = `kill $kidpid`;
LogBoth(...20 min. passed... We terminate the Eggplant
process: $ret);   
exit(0); ## no need to archive now. The child process should
do the archive
}
##
}
}