Skip to content

subprocess-kill-without-reap

Reap a locally owned subprocess after killing it on timeout.

Why

Sending a kill signal does not wait for process termination or collect the exit status; deterministic cleanup still requires waiting or communication.

Fix

After kill(), call communicate() when owning captured pipes, or wait() when output is handled separately; an enclosing Popen context manager can also own cleanup.

Examples

Before — flagged Killing does not complete cleanup
app/processes.py
import subprocess
def run(args):
process = subprocess.Popen(args)
try:
process.communicate(timeout=1)
except subprocess.TimeoutExpired:
process.kill()
After — preferred Drain and wait after killing
app/processes.py
import subprocess
def run(args):
process = subprocess.Popen(args)
try:
process.communicate(timeout=1)
except subprocess.TimeoutExpired:
process.kill()
process.communicate()