Topic
  • 6 replies
  • Latest Post - ‏2011-03-23T16:14:21Z by dcorlette
dcorlette
dcorlette
4 Posts

Pinned topic Script PID is incorrect?

‏2011-03-11T18:03:40Z |
Hi folks, running into a strange problem here.
I have a very simple test script, like this:
----
#!/bin/sh
while 1 ; do
echo "PID in loop: " $$ >> /tmp/testpid.out
sleep 10
done
----

As expected, when I run this and watch the testpid.out file, I see something like this:
PID in loop: 827458
PID in loop: 827458

And if I do a:
  1. ps ax | grep testpid
827458 pts/0 A 0:00 /bin/sh ./testpid.sh

All looks good.

OK, so now I modify the script to do this:
---
#!/bin/sh
echo "Initial PID: " $$ >> /tmp/testpid.out
runthis() {
while 1 ; do
echo "PID in loop: " $$ >> /tmp/testpid.out
sleep 10
done
}
runthis &
---
(so I can put the script in the background)

When I run this, I get output like this in testpid.out:
Initial PID: 737340
PID in loop: 737340
PID in loop: 737340

But when I do a process listing, what I see is:
  1. ps ax | grep testpid
630858 pts/0 A 0:00 /bin/sh ./testpid.sh

The process IDs don't match! Not only that, but if I do:
  1. ps ax | grep 737340
I get no results.

I can literally sit there and watch the script continue to write a bogus PID to the output file, and at the same time run process listings showing that no such PID exists. It seems that the '$$' special ksh variable doesn't work here.

Any idea what's going on? Is this a bug?
Updated on 2011-03-23T16:14:21Z at 2011-03-23T16:14:21Z by dcorlette
  • haubi
    haubi
    37 Posts

    Re: Script PID is incorrect?

    ‏2011-03-14T09:14:19Z  
    The specification of $$ is to expand to the process ID of the invoked shell.

    Putting runthis() in background invokes a second shell process (fork) without setting up a new "Shell Execution Enviornment", so $$ stays unmodified.

    HTH,
    /haubi/
  • dcorlette
    dcorlette
    4 Posts

    Re: Script PID is incorrect?

    ‏2011-03-15T01:52:23Z  
    • haubi
    • ‏2011-03-14T09:14:19Z
    The specification of $$ is to expand to the process ID of the invoked shell.

    Putting runthis() in background invokes a second shell process (fork) without setting up a new "Shell Execution Enviornment", so $$ stays unmodified.

    HTH,
    /haubi/
    Thanks for the response!

    Interesting. I thought that backgrounding a process just meant disconnecting from the terminal. Not sure why a fork is necessary.

    So is there a way for a script to put itself in the background without making it lose track of its own PID?
  • haubi
    haubi
    37 Posts

    Re: Script PID is incorrect?

    ‏2011-03-21T12:36:28Z  
    • dcorlette
    • ‏2011-03-15T01:52:23Z
    Thanks for the response!

    Interesting. I thought that backgrounding a process just meant disconnecting from the terminal. Not sure why a fork is necessary.

    So is there a way for a script to put itself in the background without making it lose track of its own PID?
    Need to say that I don't have any experience in "controlling a terminal".

    However, I do see a difference between "disconnecting from the terminal" and "backgrounding".
    While there are situations where it does make sense to combine them: From a technical point of view they do not correlate in any way.

    First of all: Starting a new process always includes a fork().

    For backgrounding, I understand the old (=first) process (the shell showing the prompt within the terminal) to continue its work (showing the prompt) without waiting for the new (=second) process to finish. It is up to the old process to decide whether to wait for the new process or not, so a new process cannot put itself into "background" from the old process' point of view.

    However, the second process can start another (=third) process in "background", and then exit (without waiting for the third), so the old (first) process does see it's child (the second process) to finish, without knowing that there was another (third) process started. This is what your script (started as the second process) does, although without reinitializing the shell's environment for the third process.

    But still, even the third process is connected to the "controlling terminal" (whatever this technically means), even it turns out it cannot write to stdout/stderr any more (don't know the reason for that).

    Eventually, this script may be of some help for you, where in the most interesting line:
    • "nohup ... >> ... 2>&1 </dev/null" is what I'd call "disconnecting from the terminal",
    • "$0" (along "$@") is to start a new shell environment (reinitializing $$) for the script ($0) with same arguments ("$@"), and
    • "&" in the same line is for the "backgrounding".
    
    #! /bin/sh   echo 
    "Initial PID: $$"   
    
    if [ 
    "${1-}" != 
    '--foreground' ]; then echo 
    "demonizing..." # the most interesting line: nohup 
    "$0" --foreground 
    "$@" >> /tmp/testpid.out 2>&1 </dev/
    
    null & echo 
    "demonized as $!" exit $? fi   # drop 
    '--foreground' argument shift   
    
    while 
    
    true 
    
    do echo 
    "PID in loop: $$" sleep 10 done   exit 0
    

    As an additional feature, you can use the '--foreground' argument for debugging purpose...

    HTH,
    /haubi/
  • dcorlette
    dcorlette
    4 Posts

    Re: Script PID is incorrect?

    ‏2011-03-21T19:50:43Z  
    Interesting, thanks for the suggestion.

    I guess my confusion lies not in the process of forking (yes, I understand that to fork, I need a new process), but why the '&' character which causes things to be put into the background requires a new process to be started at all.

    I would think that '&' would just cause the aforementioned process to disconnect STDIN and STDOUT from the terminal, that's it. Instead it appears to do that, and also start another process. I should note that this does NOT happen this way on e.g. Linux - the script retains the same PID even after being put in the background - indeed, it's the same process, it just doesn't talk to the terminal any more, and the terminal doesn't wait for it any more.

    So maybe this is just an AIX oddity, some developer decided to implement it this way without necessarily thinking about the implications. In any case, I have a workaround so I am satisfied.

    Thanks for your responses.
  • haubi
    haubi
    37 Posts

    Re: Script PID is incorrect?

    ‏2011-03-22T09:12:47Z  
    • dcorlette
    • ‏2011-03-21T19:50:43Z
    Interesting, thanks for the suggestion.

    I guess my confusion lies not in the process of forking (yes, I understand that to fork, I need a new process), but why the '&' character which causes things to be put into the background requires a new process to be started at all.

    I would think that '&' would just cause the aforementioned process to disconnect STDIN and STDOUT from the terminal, that's it. Instead it appears to do that, and also start another process. I should note that this does NOT happen this way on e.g. Linux - the script retains the same PID even after being put in the background - indeed, it's the same process, it just doesn't talk to the terminal any more, and the terminal doesn't wait for it any more.

    So maybe this is just an AIX oddity, some developer decided to implement it this way without necessarily thinking about the implications. In any case, I have a workaround so I am satisfied.

    Thanks for your responses.
    > I would think that '&' would just cause the aforementioned process to disconnect STDIN and STDOUT from the terminal, that's it. Instead it appears to do that,

    As far as I can tell, '&' really should do nothing with STDOUT/STDERR at all.
    And for STDIN, the backgrounded process would stop until "foregrounded" (using 'fg' shell command) when trying to read, but can't say how that stop is initiated.

    > I should note that this does NOT happen this way on e.g. Linux - the script retains the same PID even after being put in the background - indeed, it's the same process,

    I do see the same behaviour (new process/new pid upon '&' while retaining '$$') even on Linux (using bash) here...

    > it just doesn't talk to the terminal any more, and the terminal doesn't wait for it any more.

    I've added 'set -x' just before the definition of 'runthis()' (from your initial post), and I do see its output (to STDERR) while running in background (on Linux).

    So I don't think there's any difference regarding '&' between bash (Linux) and ksh (AIX).

    BTW: Have you tried bash on AIX?

    /haubi/
  • dcorlette
    dcorlette
    4 Posts

    Re: Script PID is incorrect?

    ‏2011-03-23T16:14:21Z  
    > As far as I can tell, '&' really should do nothing with STDOUT/STDERR at all.

    Yes, I guess that's true - many services are nice and also disconnect STDOUT/STDERR so they don't pollute the console, but it appears to be voluntary.

    > And for STDIN, the backgrounded process would stop until "foregrounded" (using 'fg' shell command) when trying to read, but can't say how that stop is initiated.

    I don't believe that's true - putting an '&' to background the script causes it to stop controlling the console, but it continues to run. Issuing a Ctrl-Z puts a process in the background and stops it, true, but that's different.

    >> I should note that this does NOT happen this way on e.g. Linux - the script retains the same PID even after being put in the background - indeed, it's the same process,

    > I do see the same behaviour (new process/new pid upon '&' while retaining '$$') even on Linux (using bash) here...

    I did some more tests and you are correct, my earlier tests were depending on $$ being correct, which as we now know is not the case. There was some additional confusion because the AIX startsrc process appears to spawn three copies of everything, which was making multiple UUIDs show up in that output file.

    Anyway, we can kill this thread, thanks for the interesting discussion. I personally think that '$$' should never be an actual invalid PID, but then again I didn't design UNIX so I certainly don't know all the implications and complications ;-)