fix: kill_process_tree waits for the reap by default (#36589)
This commit is contained in:
@@ -443,7 +443,9 @@ class Runtime:
|
|||||||
from sglang.srt.utils import kill_process_tree
|
from sglang.srt.utils import kill_process_tree
|
||||||
|
|
||||||
if self.pid is not None:
|
if self.pid is not None:
|
||||||
kill_process_tree(self.pid)
|
# Note(kpham-sgl): __del__ routes here, so the reap wait has to stay
|
||||||
|
# off -- blocking inside GC stalls whichever thread is allocating.
|
||||||
|
kill_process_tree(self.pid, wait_timeout=None)
|
||||||
self.pid = None
|
self.pid = None
|
||||||
|
|
||||||
def start_profile(self):
|
def start_profile(self):
|
||||||
|
|||||||
@@ -3166,7 +3166,7 @@ class TokenizerManager(TokenizerControlMixin, TokenizerManagerScoreMixin):
|
|||||||
deadline = time.monotonic() + 15
|
deadline = time.monotonic() + 15
|
||||||
while time.monotonic() < deadline and collect_scheduler_processes():
|
while time.monotonic() < deadline and collect_scheduler_processes():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
kill_process_tree(os.getpid(), include_parent=True)
|
kill_process_tree(os.getpid(), include_parent=False, wait_timeout=60)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def force_exit_handler(self):
|
def force_exit_handler(self):
|
||||||
|
|||||||
@@ -2219,14 +2219,17 @@ def kill_process_tree(
|
|||||||
parent_pid,
|
parent_pid,
|
||||||
include_parent: bool = True,
|
include_parent: bool = True,
|
||||||
skip_pid: int = None,
|
skip_pid: int = None,
|
||||||
wait_timeout: Optional[float] = None,
|
wait_timeout: Optional[float] = 60,
|
||||||
):
|
):
|
||||||
"""Kill the process and all its child processes.
|
"""Kill the process and all its child processes.
|
||||||
|
|
||||||
`wait_timeout` (seconds) blocks until every killed process is reaped and
|
`wait_timeout` (seconds) blocks until every killed process is reaped and
|
||||||
raises `RuntimeError` on timeout; `None` is fire-and-forget. The
|
raises `RuntimeError` on timeout. SIGKILL only queues the teardown, so
|
||||||
`parent_pid == os.getpid()` branch calls `sys.exit(0)` and cannot wait
|
returning without waiting leaves the GPU context, the pinned host memory
|
||||||
for itself -- use `include_parent=False` if child reap must finish first.
|
and the ports held for seconds; pass `None` only where blocking is
|
||||||
|
unacceptable, such as a `__del__`. The `parent_pid == os.getpid()` branch
|
||||||
|
calls `sys.exit(0)` and cannot wait for itself -- use
|
||||||
|
`include_parent=False` if child reap must finish first.
|
||||||
"""
|
"""
|
||||||
logger.info(
|
logger.info(
|
||||||
f"kill_process_tree called: parent_pid={parent_pid}, "
|
f"kill_process_tree called: parent_pid={parent_pid}, "
|
||||||
@@ -2239,10 +2242,10 @@ def kill_process_tree(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
itself = psutil.Process(parent_pid)
|
itself = psutil.Process(parent_pid)
|
||||||
|
children = itself.children(recursive=True)
|
||||||
except psutil.NoSuchProcess:
|
except psutil.NoSuchProcess:
|
||||||
return
|
return
|
||||||
|
|
||||||
children = itself.children(recursive=True)
|
|
||||||
killed = []
|
killed = []
|
||||||
for child in children:
|
for child in children:
|
||||||
if child.pid == skip_pid:
|
if child.pid == skip_pid:
|
||||||
|
|||||||
Reference in New Issue
Block a user