Skip to content

Fix: enforce single root Remote L3 startup deadline; split attach vs runtime timeout#1432

Merged
ChaoWao merged 1 commit into
hw-native-sys:mainfrom
ChaoWao:feat/p0.3-deadline-hardening
Jul 22, 2026
Merged

Fix: enforce single root Remote L3 startup deadline; split attach vs runtime timeout#1432
ChaoWao merged 1 commit into
hw-native-sys:mainfrom
ChaoWao:feat/p0.3-deadline-hardening

Conversation

@ChaoWao

@ChaoWao ChaoWao commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

#1420 delivered the shape of a single-root Remote L3 startup budget but left it resettable at several hops and clamped the runtime command timeout to leftover startup budget (KNOWN_ISSUES.md / P0.3 roadmap).

  • R2 [high] — make the single root deadline a hard wall across the whole parent → daemon → runner → native-attach chain.
  • R4 [medium] — separate the attach timeout from the post-READY runtime command timeout.

Wire contract: the cross-machine parent → daemon wire carries only a duration (startup_remaining_s) — no absolute monotonic timestamp crosses machines. The same-host daemon → runner handoff is a private local manifest (written to a tempfile the daemon Popen-spawns the runner with), and it additionally carries startup_deadline_monotonic — the daemon's absolute deadline on the shared CLOCK_MONOTONIC, so the runner's deadline equals the daemon's and spawn/import/registry time is charged (not restarted from a frozen duration).

Changes

Parent (worker.py)

  • Numeric-only endpoints (or localhost), validated in add_remote_worker before any startup resource: getaddrinfo is unbounded/uncancellable, so a hostname is rejected up front rather than mid-activation (which would roll back the forked tree). RemoteWorkerSpec + docs/remote-l3-worker-design.md state the contract.
  • _open_remote_session(deadline): AI_NUMERICHOST resolution can't block; each per-address connect and each recv derive from the deadline; wire budget + send timeout derived after the manifest build.
  • Final root-deadline gate in the READY-commit critical section, applied to every hierarchical worker (a local child may have remote descendants).

Remote (remote_l3_worker.py, remote_l3_session.py)

  • Daemon builds one absolute deadline and hands the runner its absolute startup_deadline_monotonic; runner uses it verbatim, established before registry install. Command accept (still attach phase) is bounded by the remaining startup budget, not session_timeout_s. The command connection is then forced blocking (settimeout(None), since accept() inherits socket.getdefaulttimeout() which a user module could have set) — the command loop idle-waits for the next frame, so a finite timeout would self-destruct a healthy idle session; the loop ends when the parent closes the command socket (read_frame sees EOF).

C++ (remote_endpoint.{h,cpp}, worker.{h,cpp}, worker_bind.h)

  • RemoteL3SocketTransport(attach_timeout_s, runtime_timeout_s), one attach_deadline_; connect_tcp_socket takes the absolute Deadline directly. Command/HELLO/health connect use attach_deadline_; runtime frame I/O + health loop use runtime_timeout_s_. The connected fd stays O_NONBLOCK for its whole life and all frame I/O polls for readiness under a deadline, so a large write to a stalled reader cannot outlast the deadline in one blocking send() (the earlier per-send MSG_DONTWAIT was not portable — hung ~47s on macOS); recv paths handle EAGAIN. add_remote_l3_socket + binding gain both timeouts (internal C++ ABI, not wire).

Testing (repro-first, device-free)

  • Python: deterministic fake clock; single-root-budget suite on the deadline API; attach/runtime split; READY-commit-gate (unconditional for hierarchical startup); numeric-only endpoint contract (hostname rejected at registration); command-accept bounded by the startup deadline (distinct from session_timeout); daemon-hands-runner-absolute-deadline + runner-uses-it-verbatim; bounded-connect; send-time recompute. Behavioral tests fail against the pre-fix sources.
  • cpput (13 tests): 6-arg ctor (compile-break repro); HELLO bounded by attach (~0.2s); runtime read survives an elapsed attach deadline (reply at 0.5s); runtime write to a stalled reader times out at the runtime deadline (~0.5s on the nonblocking fd); ctor validation.

Local verification: cpput test_remote_endpoint 13/13 (Linux); tests/ut/py/test_worker/ + remote lifecycle/protocol + callable_identity 397 passed / 2 skipped; ruff + ruff-format + pyright + clang-format + clang-tidy + cpplint + markdownlint all pass. macOS runtime-write regression is fixed by the O_NONBLOCK change (CI will confirm). Hardware N/A (sim-only control plane).

The roadmap entry for hierarchical remote startup should stay PARTIAL until the test-level-hard-timeout + full "local child READY then remote fails" zero-residual (PID/SHM/session) matrix exists — out of scope here.

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Remote L3 startup now uses a shared absolute deadline across Python session setup and activation. The C++ transport separates attach and runtime timeouts, while bindings, worker APIs, and tests are updated for the new contracts.

Changes

Remote L3 deadline budgeting

Layer / File(s) Summary
Transport timeout contract
src/common/hierarchical/remote_endpoint.*, src/common/hierarchical/worker.*, python/bindings/worker_bind.h
Remote transport APIs now accept separate attach and runtime timeouts, with attach-phase operations bounded by one deadline and runtime I/O using fresh runtime deadlines.
Python startup deadline propagation
python/simpler/worker.py, python/simpler/remote_l3_worker.py, python/simpler/remote_l3_session.py
Remote startup, resolution, connection, session opening, activation, and READY publication consume a shared absolute deadline.
Deadline behavior validation
tests/ut/cpp/hierarchical/test_remote_endpoint.cpp, tests/ut/py/test_remote_l3_lifecycle.py, tests/ut/py/test_worker/test_remote_startup_budget.py, tests/ut/py/test_callable_identity.py
Tests cover attach/runtime timeout separation, deadline exhaustion, bounded networking, READY gating, startup budget propagation, and updated mock signatures.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Worker
  participant RemoteRunner
  participant RemoteSession
  participant RemoteL3SocketTransport

  Worker->>RemoteRunner: start with remaining startup budget
  RemoteRunner->>RemoteSession: propagate shared startup deadline
  Worker->>RemoteSession: open session using absolute deadline
  RemoteSession->>RemoteL3SocketTransport: attach with remaining attach timeout
  RemoteL3SocketTransport-->>Worker: attach result
  Worker->>Worker: recheck deadline before READY
Loading

Possibly related PRs

Poem

A bunny hopped through deadlines tight,
Split attach from runtime night.
HELLO waits, then frames flow free,
One root clock guards READY.
“Hop hooray!” said the rabbit with glee.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: enforcing a single startup deadline and splitting attach versus runtime timeouts.
Description check ✅ Passed The description is directly aligned with the PR and explains the deadline and timeout split changes in detail.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ChaoWao
ChaoWao force-pushed the feat/p0.3-deadline-hardening branch 6 times, most recently from 9723ee5 to 1370faa Compare July 22, 2026 07:03
…plit attach vs runtime timeout

hw-native-sys#1420 delivered the shape of a single-root remote-L3 startup budget but
left the budget resettable at several hops, and clamped the runtime
command timeout to leftover startup budget.

R2 [high] — make the single root deadline a hard wall across the whole
parent -> daemon -> runner -> native-attach chain. R4 [medium] —
separate the attach timeout from the post-READY runtime command timeout.
The cross-machine parent -> daemon wire carries only a duration; no
cross-machine wire fields are added.

Parent (worker.py):
- Remote endpoints are numeric-only (or localhost), validated in
  add_remote_worker before any startup resource: getaddrinfo resolution
  is unbounded and uncancellable, so a hostname is rejected up front
  rather than mid-activation (which would roll back the whole forked
  tree). RemoteWorkerSpec and the design doc state the contract.
- _open_remote_session(deadline): AI_NUMERICHOST resolution cannot block;
  every per-address connect and each recv derive from the deadline; the
  wire budget and send timeout are derived after the manifest build.
- The final root-deadline gate lives in the READY-commit critical section
  and applies to every hierarchical worker (a local child may have remote
  descendants), so a thread descheduled after startup cannot publish
  READY late.

Remote (remote_l3_worker.py, remote_l3_session.py):
- The daemon builds one absolute deadline up front and, over the private
  same-host daemon -> runner manifest, hands the runner its ABSOLUTE
  monotonic deadline (shared CLOCK_MONOTONIC). The runner uses it verbatim,
  so its deadline equals the daemon's and spawn/import/registry time is
  charged; it establishes the deadline before registry install.
- Waiting for the parent to attach is still the attach phase: command
  accept is bounded by the remaining startup budget, not session_timeout_s.
  The command connection then stays blocking: the command loop idle-waits
  for the next frame (forced blocking, since accept() inherits the process
  default timeout), so a finite timeout would tear down a healthy idle
  session; the loop ends when the parent closes the command socket (EOF).

C++ (remote_endpoint.{h,cpp}, worker.{h,cpp}, worker_bind.h):
- RemoteL3SocketTransport takes attach_timeout_s + runtime_timeout_s and
  one attach_deadline_. connect_tcp_socket takes the absolute Deadline
  directly (resolution + each connect derive from it). Command/HELLO/
  health connect use attach_deadline_; runtime frame I/O + the health loop
  use runtime_timeout_s_. The connected fd stays O_NONBLOCK for its whole
  life and all frame I/O polls for readiness under a deadline, so a large
  write to a stalled reader cannot outlast the deadline in one blocking
  send() (the earlier per-send MSG_DONTWAIT was not portable and hung ~47s
  on macOS); recv/read paths handle EAGAIN. add_remote_l3_socket and its
  binding gain both timeouts (internal C++ ABI; not wire).

Tests are repro-first (discipline §3): deterministic fake clock; the
single-root-budget suite on the deadline API; attach-vs-runtime split;
READY-commit-gate (unconditional for hierarchical startup); numeric-only
endpoint contract (hostname rejected at registration); command-accept
bounded by the startup deadline (distinct from session_timeout);
daemon-hands-runner-absolute-deadline and runner-uses-it-verbatim
regressions; and cpput tests proving the HELLO read is bounded by the
attach timeout, a runtime read survives an elapsed attach deadline, and a
runtime write to a stalled reader times out at the runtime deadline.
@ChaoWao
ChaoWao merged commit 8fd7c27 into hw-native-sys:main Jul 22, 2026
16 checks passed
@ChaoWao
ChaoWao deleted the feat/p0.3-deadline-hardening branch July 22, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant