Skip to content

Commit d81258b

Browse files
authored
run-task: wait on child processes when we're pid 1 (#810)
Avoid leaving zombie processes around in the container while the task is running. Ported from gecko (bug 1967974)
1 parent 80edd71 commit d81258b

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

src/taskgraph/run-task/run-task

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import socket
2828
import stat
2929
import subprocess
3030
import sys
31+
import threading
3132
import time
3233
import urllib.error
3334
import urllib.request
@@ -121,6 +122,17 @@ def print_line(prefix, m):
121122
sys.stdout.buffer.flush()
122123

123124

125+
def reap_zombies(main_subprocess):
126+
"""Wait for main_subprocess to exit, while awaiting any other child processes"""
127+
while main_subprocess.poll() is None:
128+
with main_subprocess._waitpid_lock:
129+
if main_subprocess.returncode is not None:
130+
return
131+
pid, status = os.wait()
132+
if pid == main_subprocess.pid:
133+
main_subprocess._handle_exitstatus(status)
134+
135+
124136
def _call_windows_retry(func, args=(), retry_max=5, retry_delay=0.5):
125137
"""
126138
It's possible to see spurious errors on Windows due to various things
@@ -278,6 +290,13 @@ def run_command(prefix, args, *, extra_env=None, cwd=None):
278290

279291
stdout = io.TextIOWrapper(p.stdout, encoding="latin1")
280292

293+
if os.getpid() == 1:
294+
# in docker we're init, so we get to adopt unawaited zombies
295+
reaper_thread = threading.Thread(target=reap_zombies, args=(p,))
296+
reaper_thread.start()
297+
else:
298+
reaper_thread = None
299+
281300
while True:
282301
data = stdout.readline().encode("latin1")
283302

@@ -286,6 +305,8 @@ def run_command(prefix, args, *, extra_env=None, cwd=None):
286305

287306
print_line(prefix, data)
288307

308+
if reaper_thread:
309+
reaper_thread.join()
289310
return p.wait()
290311

291312

0 commit comments

Comments
 (0)