Package · thread · deep dive

PID reuse & signals

Thread controls a process through a proc_open handle; Signal controls one through a bare PID. That difference is why one is safe for lifecycle management and the other needs care.

Why Thread is reliable

Thread never signals a raw number in a vacuum. isAlive(), join(), and every signal method check the proc_open handle via proc_get_status, which is bound to the exact child the parent spawned. When that process exits and is reaped, the handle knows — there is no window where the handle could point at some other process.

Why raw PIDs are risky

Signal calls posix_kill($pid, ...) on a number you supply. PIDs are a finite, reused resource: once a process exits and is reaped, the OS is free to hand its number to a completely unrelated process. So a PID you captured a moment ago can, by the time you signal it, belong to something else entirely — and your SIGTERM/SIGKILL lands on the wrong target.

That’s why Signal is documented as “fresh PIDs only,” and why lifecycle control should go through Thread.

The zombie subtlety

There’s a sharper edge inside isProcessRunning(). A zombie (state Z) is a process that has already exited but hasn’t yet been reaped by its parent. A zombie still answers posix_kill($pid, 0) — the probe returns “exists,” even though the process can do no work and should count as gone.

So isProcessRunning() doesn’t stop at the probe. After confirming the PID responds, it checks the process state and treats a zombie as not running:

  • Linux — reads /proc/<pid>/status and matches ^State:\s+Z.
  • macOS / BSD — runs ps -o state= -p <pid> (with $pid cast to int, so no shell injection) and checks for a leading Z.
text
posix_kill(pid, 0)  →  false          → not running
                  →  true, state Z  → not running (zombie)
                  →  true, alive    → running

Practical rule

Use Thread methods to stop and wait for work you started. Reach for Signal only with a PID obtained immediately before the call — e.g. reaping a known, still-live child.