Does the PID of a child process become available for reuse if the parent process is still running?
Asked Answered
A

1

5

I am running on *nix based OS's and have a script that initiates multiple processes concurrently. The main goal for me is to initiate these processes concurrently, and gather the returned exit statuses for each of the processes. I've found that using wait(pid) will achieve this, since all child processes are owned by the parent process. However, I am concerned that once a child process (one of the concurrent processes initiated) completes, its PID will be released and made available to be recycled within the system.

So I guess the question is, if a parent process initiates several child processes concurrently, will the PID of a child process that completes be made available to the system for recycling prior to the parent process completing? If so, how can I best obtain the exit statuses of each of the child processes?

Example of bash script below:

local file=$1
local count=0
<files are split; and suffixed with aa,ab,ac,ad>

/home/text/concurrencyTest.sh $file-aa >> /home/text/$file-aa.log 2>&1 &
/home/text/concurrencyTest1.sh $file-ab >> /home/text/$file-ab.log 2>&1 &
/home/text/concurrencyTest2.sh $file-ac >> /home/text/$file-ac.log 2>&1 &
/home/text/concurrencyTest3.sh $file-ad >> /home/text/$file-ad.log 2>&1 &

for job in `jobs -p`
do
    echo "Job: $job"
    wait "$job"
    rc=$?
    echo "RC for $job is $rc"
    if [[ rc -ne 0 ]]; then
        FAIL[$count]="$job"
        ((count++))
    fi
done
if [[ $count -ne 0 ]]; then
    echo "ERROR: $count Job(s) Failed!"
    echo "Failed Process PID(s): ${FAIL[@]}"
    echo "Failed Processing for file: $file"
    return 1
fi
Astra answered 11/12, 2015 at 19:11 Comment(0)
H
7

The PID of a child process becomes available for reuse when the parent process calls wait or waitpid (or any other function of that family such as wait3, wait4, etc.).

When the child dies, it stays behind as a zombie — an entry in the process table with no process behind it, which remains behind just to reserve the process ID and store the exit status. Calling waitpid blocks until the designated child process dies (or returns immediately if it's already dead), retrieves the child's status code, and reaps the zombie (i.e. removes the process table entry, freeing the process ID for reuse). Calling wait is similar, but returns as soon as one child process has died.

If the parent process ignores the SIGCHLD signal at the time the process dies, then the process is not turned into a zombie and its PID becomes available for reuse immediately. The parent's status vis-à-vis SIGCHLD matters in other ways; see e.g. POSIX for the gritty details.

If the parent process dies before the child, the child is said to be an orphan adopted by init, the process with PID 1. It is part of init's job to reap orphans.

In a shell script, the wait builtin with is a wrapper around the wait system call. If the script has multiple children, wait with no argument blocks until all of them have died, and wait with some arguments blocks until all the specified processes have died (there's no way to wait until one process as died without specifying which). If wait $pid1 returns, it's possible that $pid2 has already died and has been reused for another process; however, the shell keeps track of $pid2's status code even so, and a subsequent wait $pid2 will return its status code. You should not fork a new background job until then, however, to avoid confusion in case $pid2 was reused to a background job.

Heir answered 11/12, 2015 at 19:28 Comment(3)
Excellent! Thank you for the response. It's my understanding then, that even though one of the child processes PIDs may have been recycled and used for something else within the system (because it exited with some status), the subsequent wait $pid2 will still return the correct exit status for the child processes PID that I am concerned with. This is because the shell maintains the status of the child process at exit, even though the PID may have been recycled. Thanks again!Astra
Will the subsequent wait $pid2 still return the correct status code, if the PID for $pid2 has already been recycled and used for a separate background process initiated outside of the parent process?Astra
@Astra If $pid2 has been recycled by anything other than a background job of that shell, the shell won't even know about it, it'll just return the value that it stored. It's only in the case where two un-waited background jobs end up having the same PID that something could go wrong, and that can only happen if the second job was forked after the first one had died and the script had executed the wait builtin for a different PID.Pitiable

© 2022 - 2024 — McMap. All rights reserved.