pythonmultiprocessingpid

Python Multiprocessing - detect if PID is alive


I need to detect if the PID of a grandchild process is alive. Because the multiprocessing.Process() object is non-pickleable (for security reasons), I can't pass it up the process hierarchy and call process.is_alive() so I need to pass the PID and use that instead.

The following code successfully identifies that the PID is active however when I manually kill the process (in Ubuntu using kill in bash) it erroneously continues detecting it as active. process.is_alive() on the other hand works correctly. How can I reliably detect PID state using only the PID?

import os
import time
from multiprocessing import Process 

def pid_is_alive(pid):
    try:
        os.kill(pid, 0)  # Send signal 0 to check if the process exists.
    except ProcessLookupError:
        return False
    return True

def worker():
    print("worker started")
    print(os.getpid())
    while True:
        time.sleep(1)
        print("worker running")

p = Process(target=worker)
p.start()

while True:
    time.sleep(1)
    # Check if the PID is alive
    if pid_is_alive(p.pid):
        print(f'PID {p.pid} is alive.')
    else:
        print(f'PID {p.pid} is not alive.')
    
    # if p.is_alive():
    #     print("Process is alive")
    # else:
    #     print("Process is not alive")
    

Solution

  • Actually, the program behaves correctly.

    When you kill the process, it goes to the defunct (a.k.a. zombie) state until its parent does a wait(). In that time the PID is still in use and the is_alive() returns True - as you see, a more descriptive name would be PID_exists().

    There are several options:

    1. make sure the parent awaits its children, some lower lever programs install a SIGCHLD handler to receive a notification.
    2. use the double fork technique to orphan the child process. The PID 1 process will become a new parent and will wait for it. This is the easiest option IMO - if you don't care losing the exit status.
    3. check the process status. I would not recommend this, because it is the least portable option.