fix(code-runtime-python): reset the inherited SIGXCPU disposition and mask at startup

The reviewer's standing issue: the child inherits the host's SIGXCPU
disposition and signal mask — if the host ignores or blocks SIGXCPU, the soft
RLIMIT_CPU fires but cannot stop the child, and the hard limit's SIGKILL then
classifies a definite CPU overrun as worker-exit instead of a timeout. The
bootstrap now resets SIGXCPU to SIG_DFL and unblocks it before any model code
runs (the settle-time enforcer already restores SIG_DFL for a program that
traps or masks the signal mid-run; this closes the inherited-state gap). The
zh README's outer wire section also gains the truncation-exception sentence to
match the en side.
This commit is contained in:
Chinesezjc
2026-08-31 15:04:43 +08:00
committed by Tianyi Cui
parent fa0565032f
commit 7b9db83f86
3 changed files with 13 additions and 2 deletions
@@ -1195,6 +1195,17 @@ async def _run(channel: ProtocolChannel) -> None:
# can `except ToolCallError as e:` and read the member property.
namespaces[declared["name"]] = error_class
# The child inherits the host's SIGXCPU disposition and signal mask. If
# the host ignores or blocks SIGXCPU, the soft RLIMIT_CPU fires but cannot
# stop the child — the hard limit's SIGKILL then classifies a definite CPU
# overrun as substrate death (worker-exit) instead of a timeout. Reset to
# the default disposition and unblock before any model code runs (the
# settle-time enforcer already restores SIG_DFL for a program that traps or
# masks the signal mid-run; this closes the inherited-state gap).
signal.signal(signal.SIGXCPU, signal.SIG_DFL)
if getattr(signal, "pthread_sigmask", None) is not None:
signal.pthread_sigmask(signal.SIG_UNBLOCK, (signal.SIGXCPU,))
channel.send_sync({"type": "boot-ack"})
# 3. Start a reply-pump task before the run message: replies can arrive