5

Is it possible to stop a PID from being reused?

For example if I run a job myjob in the background with myjob &, and get the PID using PID=$!, is it possible to prevent the linux system from re-using that PID until I have checked that the PID no longer exists (the process has finished)?

In other words I want to do something like:

myjob &
PID=$!
do_not_use_this_pid $PID
wait $PID
allow_use_of_this_pid $PID

The reasons for wanting to do this do not make much sense in the example given above, but consider launching multiple background jobs in series and then waiting for them all to finish.

Some programmer dude rightly points out that no 2 processes may share the same PID. That is correct, but not what I am asking here. I am asking for a method of preventing a PID from being re-used after a process has been launched with a particular PID. And then also a method of re-enabling its use later after I have finished using it to check whether my original process finished.

Since it has been asked for, here is a use case:

  • launch multiple background jobs
  • get PID's of background jobs
  • prevent PID's from being re-used by another process after background job terminates
  • check for PID's of "background jobs" - ie, to ensure background jobs finish
  • [note if disabled PID re-use for the PID's of the background jobs those PIDs could not be used by a new process which was launched after a background process terminated]*
  • re-enable PID of background jobs
  • repeat

*Further explanation:

  • Assume 10 jobs launched
  • Job 5 exits
  • New process started by another user, for example, they login to a tty
  • New process has same PID as Job 5!
  • Now our script checks for Job 5 termination, but sees PID in use by tty!
Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
  • The kernel already disallows it. No two processes may have the same pid. – Some programmer dude Nov 01 '16 at 12:17
  • @Someprogrammerdude Okay I didn't explain this well enough, I'll edit my question, one sec – FreelanceConsultant Nov 01 '16 at 12:20
  • 1
    Maybe you can add the use-case? Tell us what problem you are trying to solve? Related reading about [the XY problem](http://xyproblem.info/) – Some programmer dude Nov 01 '16 at 12:21
  • 3
    If this is possible, I'm gonna write a bomb: `for x in $(seq 1 PID_MAX); do do_not_use_this_pid $x; done` – Siguza Nov 01 '16 at 12:24
  • 2
    You can probably do something with `trap ... SIGCHLD` to process the child PID termination asynchronously. That way you don't have to worry about the PID getting reused after it terminates and before you can check its status. You just have to be *real* careful in your script about starting subprocesses. – Andrew Henle Nov 01 '16 at 12:25
  • I still don't understand why it matters that a new process may use the PID of a terminated process... – Jens Nov 01 '16 at 12:27
  • @AndrewHenle Can you add more info on this? Why do i need to be careful? What is trap, is it a bash command? – FreelanceConsultant Nov 01 '16 at 12:27
  • @Jens Then I can't check if the original process exited. – FreelanceConsultant Nov 01 '16 at 12:29
  • Reusing PIDs shouldn\`t pose any problems to detect process termination post-factum. See [this question](http://stackoverflow.com/questions/40205638/detecting-a-stale-pid-file-in-a-unix-environment). – hidefromkgb Nov 01 '16 at 12:29
  • @hidefromkgb That question suggests the start time/date in combination with PID should be enough to uniquely determine all processes run on a system, so I would also have to check for the start date/time of a process if the PID exists. – FreelanceConsultant Nov 01 '16 at 12:34
  • @user3728501 See https://linux.die.net/Bash-Beginners-Guide/sect_12_02.html for `trap` documentation. Basically, `trap command SIGNAL` will run `command` asynchronously when `SIGNAL` is received. Your shell gets `SIGCHLD` *every* time a child process exits - and I mean *every* time. So if you want to use a `trap ... SIGCHLD` to control child processes/jobs, you have to be really careful selecting the commands you use in your shell. You can start with something like this: http://stackoverflow.com/questions/6769414/bash-restart-sub-process-using-trap-sigchld – Andrew Henle Nov 01 '16 at 13:06

4 Answers4

6

You can't "block" a PID from being reused by the kernel. However, I am inclined to think this isn't really a problem for you.

but consider launching multiple background jobs in series and then waiting for them all to finish.

A simple wait (without arguments) would wait for all the child processes to complete. So, you don't need to worry about the PIDs being reused.

When you launch several background process, it's indeed possible that PIDs may be reused by other processes. But it's not a problem because you can't wait on a process unless it's your child process.

Otherwise, checking whether one of the background jobs you started is completed by any means other than wait is always going to unreliable.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • 1
    To further this, if you try to wait on a process that is *not* a child of the current shell, `wait` prints an error message and exits with status 127. That won't be the exit status of a normal process, letting you distinguish between an error in one of your children and attempting to wait on a finished job whose process ID might be in use elsewhere. – chepner Nov 01 '16 at 12:52
  • 1
    `wait` has the exact problem. If I launch 2 background processes, I cannot tell in which order I should `wait` for them to finish. One may finish while I am running the command `wait` with the others PID! In which case, the PID of the finished process may become re-used. – FreelanceConsultant Nov 01 '16 at 13:15
  • Process IDs are *at least* 16 bits; are you really concerned about your machine spawning 60,000+ new processes in the time between one job finishing and a call to `wait` on the other one returning? – chepner Nov 01 '16 at 13:49
  • A problem occurs, if we want to get error code reliably of each background job, re-use of PID by kernel causes a problem. Example, sleep 10s & ===> X pidX=$! sleep 5s & ===> Y pidY=$! wait pidX wait pidY Y exits first and suppose another process is loaded into system with pid same as pidY. The 2nd wait will it that and wait complains: wait: pid pidY is not a child of this shell For such cases, the reliable way is to have background store the return code in a file and have parent fetch it from file. – BHS Jul 20 '18 at 00:11
2

Unless you've retrieved the return value of the child process it will exist in the kernel. That also means that it's pid is bound to it and can't being re-used during that time.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
0

Further suggestion to work around this - if you suspect that a PID assigned to one of your background jobs is reassigned, check it in ps to see if it still is your process with your executable and has PPID (parent PID) 1.

Stefan Hegny
  • 2,107
  • 4
  • 23
  • 26
0

If you are afraid of reusing PID's, which won't happen if you wait as other answers explain, you can use

echo 4194303 > /proc/sys/kernel/pid_max

to decrease your fear ;-)

Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • Unless I don't understand something here, if I have to `wait` for more than 1 PID then it is possible that another PID will be reused in the event the wait commands finish out of order – FreelanceConsultant Nov 01 '16 at 22:02