Skip to content

fix(python): raise TimeoutError for exec timeouts#959

Open
G4614 wants to merge 7 commits into
mainfrom
g4614/pol-100-python-timeout-error
Open

fix(python): raise TimeoutError for exec timeouts#959
G4614 wants to merge 7 commits into
mainfrom
g4614/pol-100-python-timeout-error

Conversation

@G4614

@G4614 G4614 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Raise TimeoutError from Python convenience exec APIs using an explicit timeout signal propagated through local and cloud execution paths.

Test plan:

  • cargo fmt --all
  • cargo fmt --all --check
  • python3 -m py_compile sdks/python/boxlite/exec.py sdks/python/boxlite/simplebox.py sdks/python/boxlite/sync_api/_simplebox.py sdks/python/tests/test_exec_timeout_sigalrm.py sdks/python/tests/test_sync_simplebox.py
  • BOXLITE_DEPS_STUB=1 cargo check -p boxlite-c -p boxlite -p boxlite-cli -p boxlite-python
  • BOXLITE_DEPS_STUB=1 cargo check -p boxlite
  • BOXLITE_DEPS_STUB=1 cargo test -p boxlite --features rest ws_clean_exit_emits_result -- --nocapture
  • cargo check -p boxlite-guest --target aarch64-unknown-linux-musl
  • git diff --check
  • ssh ngolo@54.169.172.226 'bash -lc "cd ~/boxlite-pr959-timeout && BOXLITE_DEPS_STUB=1 cargo check -p boxlite-guest"'
  • ssh ngolo@54.169.172.226 'bash -lc "cd ~/boxlite-pr959-cloud-check && BOXLITE_DEPS_STUB=1 cargo check -p boxlite-c"'
  • ssh ngolo@54.169.172.226 'bash -lc "cd ~/boxlite-pr959-cloud-check && BOXLITE_DEPS_STUB=1 cargo build -p boxlite-c && cd apps/runner && go test -tags boxlite_dev ./pkg/api/controllers ./pkg/boxlite"'
  • ssh ngolo@54.169.172.226 'bash -lc "cd ~/boxlite-pr959-attach-check/apps/runner && go test -tags boxlite_dev ./pkg/api/controllers -count=1"'
  • ssh ngolo@54.169.172.226 'bash -lc "cd ~/boxlite-pr959-realvm-check && cargo build -p boxlite-guest --target x86_64-unknown-linux-musl && cargo rustc -p boxlite-c --lib --crate-type staticlib && cd apps && go test -tags boxlite_dev ./runner/pkg/boxlite -run TestIntegrationExecManagerRecordsTimedOut -count=1 -v"'
  • Live dev rollout not run; current deployed dev runner was only used to confirm the pre-fix cloud API reports timed-out execs as completed/-15

Summary by CodeRabbit

  • New Features
    • Execution wait results now include a timed_out flag (alongside exit code) across APIs and SDKs.
    • REST and WebSocket execution reporting now distinguish timed_out terminal outcomes.
    • C and Go SDKs add structured “wait result” support (exit code + timeout flag); Python and CLI/SDK results expose timed_out.
  • Bug Fixes
    • Timeout state is now consistently mapped into execution status, callbacks, and response payloads (including WebSocket/REST and guest wait reporting).
  • Tests
    • Added unit/integration coverage for timed_out responses and updated Python tests to expect timeout exceptions.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Execution timeout state is recorded at process termination, propagated through guest, REST, C, Go, runner, and Python layers, and exposed through status responses, WebSocket exit frames, structured wait results, and Python timeout exceptions.

Changes

Execution Timeout Propagation

Layer / File(s) Summary
Timeout state and result contract
src/guest/src/service/exec/*, src/boxlite/src/litebox/exec.rs, src/boxlite/src/portal/interfaces/exec.rs, src/cli/src/...
Execution state records timeout termination, and ExecResult plus cancellation paths carry timed_out.
REST execution result propagation
src/boxlite/src/rest/litebox.rs
WebSocket exit frames, status probes, fallback results, and tests propagate the timeout flag.
Structured C and Go wait API
sdks/c/..., sdks/go/...
A structured wait API returns exit code and timeout state through the runtime event queue, cgo bridge, and Go bindings.
Runner timeout status and attach responses
apps/runner/pkg/...
Managed executions retain timeout state, execution-info responses report timed_out, and attach exit frames include the flag.
Python timeout results and exceptions
sdks/python/...
Python results expose timed_out, while async and sync execution APIs raise TimeoutError for timed-out commands and update tests accordingly.

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

Sequence Diagram(s)

sequenceDiagram
  participant TimeoutWatcher
  participant ExecutionState
  participant GuestWait
  participant RESTWebSocket
  participant GoExecution
  participant PythonSimpleBox
  TimeoutWatcher->>ExecutionState: kill_for_timeout(SIGTERM)
  GuestWait->>ExecutionState: was_timed_out()
  GuestWait-->>RESTWebSocket: WaitResponse.timed_out
  GoExecution->>GoExecution: WaitResult()
  GoExecution-->>PythonSimpleBox: exit_code, timed_out
  PythonSimpleBox-->>PythonSimpleBox: raise TimeoutError when timed_out
Loading

Suggested labels: bug, rust

Suggested reviewers: dorianzheng

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description misses the required Summary, Changes, How to verify, and Risks/rollout sections from the template. Rewrite it using the repo template: add Summary, Changes, How to verify, and optional Risks/rollout, and briefly describe the timeout propagation and Python API behavior.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main Python exec timeout behavior change.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch g4614/pol-100-python-timeout-error

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.

@G4614
G4614 force-pushed the g4614/pol-100-python-timeout-error branch from a632483 to 8228bb7 Compare July 14, 2026 12:22
Comment thread sdks/python/tests/test_sync_simplebox.py Fixed
@G4614
G4614 force-pushed the g4614/pol-100-python-timeout-error branch 2 times, most recently from 6284707 to c0b7c95 Compare July 15, 2026 07:50
@G4614
G4614 marked this pull request as ready for review July 15, 2026 09:23
@G4614
G4614 requested a review from a team as a code owner July 15, 2026 09:23
@boxlite-agent

boxlite-agent Bot commented Jul 15, 2026

Copy link
Copy Markdown

📦 BoxLite review — couldn't complete

claude exited 1

stdout:
{"is_error":true,"duration_api_ms":0,"num_turns":1,"stop_reason":"stop_sequence","session_id":"0ba4d4cb-e2d4-4675-bfc5-17c40cbf2fd9","total_cost_usd":0,"usage":{"input_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":0,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"},"modelUsage":{},"permission_denials":[],"terminal_reason":"api_error","fast_mode_state":"off","subtype":"success","api_error_status":403,"result":"Your organization has disabled Claude subscription access for Claude Code · Use an Anthropic API key instead, or ask your admin to enable access","type":"result","duration_ms":322,"uuid":"7502c9e8-ba57-4ed8-a15a-82795c1a027b"}

stderr:
<empty>

powered by BoxLite

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/guest/src/service/exec/timeout.rs (1)

37-41: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Record the timeout flag in the same critical section as the signal send.
wait() can reap the process and read timed_out == false in the gap between kill(SIGTERM) returning and mark_timed_out() acquiring the mutex. A small helper that sets the flag and sends SIGTERM under one lock avoids reporting a real timeout as a normal exit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/guest/src/service/exec/timeout.rs` around lines 37 - 41, Update the
timeout handling around exec_state.kill and exec_state.mark_timed_out so the
timed-out flag is set and SIGTERM is sent within one shared critical section.
Add or use a helper on the execution state that performs both operations
atomically, preserving the early return when the process has already exited and
avoiding the gap where wait() can observe timed_out as false.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/runner/pkg/boxlite/exec_manager_integration_test.go`:
- Around line 48-49: Register mgr.Stop as the test cleanup callback instead of
invoking it immediately after NewExecManager, so the manager remains active
during the test and is stopped during teardown. Update the setup around
NewExecManager while preserving the existing manager initialization.

In `@sdks/c/include/boxlite.h`:
- Around line 445-449: Document the public boxlite_execution_wait_result API in
sdks/c/include/boxlite.h:445-449, covering each parameter, callback behavior,
return value, and out_error handling; add corresponding Rust documentation for
its implementation in sdks/c/src/exec/execution.rs:171-180, keeping both
descriptions consistent.

In `@sdks/python/boxlite/simplebox.py`:
- Around line 293-297: Defensively format the timeout in the timed-out error
path so a None value cannot trigger TypeError; use a safe fallback or
representation while preserving the existing timeout details for numeric values.
Apply the same change to the corresponding timeout handling in
sdks/python/boxlite/simplebox.py lines 293-297 and
sdks/python/boxlite/sync_api/_simplebox.py lines 254-258.

---

Outside diff comments:
In `@src/guest/src/service/exec/timeout.rs`:
- Around line 37-41: Update the timeout handling around exec_state.kill and
exec_state.mark_timed_out so the timed-out flag is set and SIGTERM is sent
within one shared critical section. Add or use a helper on the execution state
that performs both operations atomically, preserving the early return when the
process has already exited and avoiding the gap where wait() can observe
timed_out as false.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 53f616d1-4a40-4fc1-abaf-df1cc8882bee

📥 Commits

Reviewing files that changed from the base of the PR and between 1cdc8f1 and 765a552.

📒 Files selected for processing (28)
  • apps/runner/pkg/api/controllers/boxlite_exec.go
  • apps/runner/pkg/api/controllers/boxlite_exec_attach.go
  • apps/runner/pkg/api/controllers/boxlite_exec_attach_test.go
  • apps/runner/pkg/api/controllers/boxlite_exec_test.go
  • apps/runner/pkg/boxlite/exec_manager.go
  • apps/runner/pkg/boxlite/exec_manager_integration_test.go
  • sdks/c/include/boxlite.h
  • sdks/c/src/event_queue.rs
  • sdks/c/src/exec/execution.rs
  • sdks/c/src/runtime.rs
  • sdks/go/bridge.c
  • sdks/go/bridge.h
  • sdks/go/bridge_callback.go
  • sdks/go/exec.go
  • sdks/python/boxlite/exec.py
  • sdks/python/boxlite/simplebox.py
  • sdks/python/boxlite/sync_api/_simplebox.py
  • sdks/python/src/exec.rs
  • sdks/python/tests/test_exec_timeout_sigalrm.py
  • sdks/python/tests/test_sync_simplebox.py
  • src/boxlite/src/litebox/exec.rs
  • src/boxlite/src/portal/interfaces/exec.rs
  • src/boxlite/src/rest/litebox.rs
  • src/cli/src/commands/serve/mod.rs
  • src/cli/src/terminal/mod.rs
  • src/guest/src/service/exec/mod.rs
  • src/guest/src/service/exec/state.rs
  • src/guest/src/service/exec/timeout.rs

Comment thread apps/runner/pkg/boxlite/exec_manager_integration_test.go Outdated
Comment thread sdks/c/include/boxlite.h
Comment thread sdks/python/boxlite/simplebox.py

@boxlite-agent boxlite-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📦 BoxLite review — 1 issue

Comment thread src/guest/src/service/exec/timeout.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
sdks/go/bridge.c (1)

64-64: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a docstring for the public function.

As per coding guidelines, comprehensive docstrings should be written for all public functions.

💬 Proposed docstring
+// cbExecutionWaitResult returns the C function pointer for the execution wait result callback.
 CExecutionWaitResultCb cbExecutionWaitResult(void) { return (CExecutionWaitResultCb)goBoxliteOnExecutionWaitResult; }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/go/bridge.c` at line 64, Add a comprehensive documentation comment
immediately before the public cbExecutionWaitResult function, describing its
purpose, return value, and callback behavior while following the project’s C
documentation conventions.

Source: Coding guidelines

sdks/go/bridge_callback.go (1)

386-406: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a docstring to the exported function.

As per coding guidelines, comprehensive docstrings should be written for all public functions. Although this is a cgo callback, it is exported and should have a docstring outlining its purpose.

💬 Proposed docstring
+// goBoxliteOnExecutionWaitResult is the callback invoked by C when execution wait completes,
+// sending the exit code, timeout state, and potential error back to the Go channel.
 //export goBoxliteOnExecutionWaitResult
 func goBoxliteOnExecutionWaitResult(exitCode C.int, timedOut C.bool, errPtr *C.CBoxliteError, userData unsafe.Pointer) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/go/bridge_callback.go` around lines 386 - 406, Add a Go doc comment
immediately above the exported goBoxliteOnExecutionWaitResult function,
describing that it handles execution-wait results from the Boxlite callback and
forwards the exit code, timeout state, and error to the waiting channel.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@sdks/go/bridge_callback.go`:
- Around line 386-406: Add a Go doc comment immediately above the exported
goBoxliteOnExecutionWaitResult function, describing that it handles
execution-wait results from the Boxlite callback and forwards the exit code,
timeout state, and error to the waiting channel.

In `@sdks/go/bridge.c`:
- Line 64: Add a comprehensive documentation comment immediately before the
public cbExecutionWaitResult function, describing its purpose, return value, and
callback behavior while following the project’s C documentation conventions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e3f6bfac-5ef5-46c2-9282-606eb90be36c

📥 Commits

Reviewing files that changed from the base of the PR and between 09019c7 and f28fa72.

📒 Files selected for processing (28)
  • apps/runner/pkg/api/controllers/boxlite_exec.go
  • apps/runner/pkg/api/controllers/boxlite_exec_attach.go
  • apps/runner/pkg/api/controllers/boxlite_exec_attach_test.go
  • apps/runner/pkg/api/controllers/boxlite_exec_test.go
  • apps/runner/pkg/boxlite/exec_manager.go
  • apps/runner/pkg/boxlite/exec_manager_integration_test.go
  • sdks/c/include/boxlite.h
  • sdks/c/src/event_queue.rs
  • sdks/c/src/exec/execution.rs
  • sdks/c/src/runtime.rs
  • sdks/go/bridge.c
  • sdks/go/bridge.h
  • sdks/go/bridge_callback.go
  • sdks/go/exec.go
  • sdks/python/boxlite/exec.py
  • sdks/python/boxlite/simplebox.py
  • sdks/python/boxlite/sync_api/_simplebox.py
  • sdks/python/src/exec.rs
  • sdks/python/tests/test_exec_timeout_sigalrm.py
  • sdks/python/tests/test_sync_simplebox.py
  • src/boxlite/src/litebox/exec.rs
  • src/boxlite/src/portal/interfaces/exec.rs
  • src/boxlite/src/rest/litebox.rs
  • src/cli/src/commands/serve/mod.rs
  • src/cli/src/terminal/mod.rs
  • src/guest/src/service/exec/mod.rs
  • src/guest/src/service/exec/state.rs
  • src/guest/src/service/exec/timeout.rs
🚧 Files skipped from review as they are similar to previous changes (22)
  • src/boxlite/src/litebox/exec.rs
  • sdks/go/bridge.h
  • sdks/python/boxlite/exec.py
  • src/cli/src/terminal/mod.rs
  • src/guest/src/service/exec/mod.rs
  • apps/runner/pkg/api/controllers/boxlite_exec_attach.go
  • src/boxlite/src/portal/interfaces/exec.rs
  • apps/runner/pkg/api/controllers/boxlite_exec.go
  • apps/runner/pkg/api/controllers/boxlite_exec_test.go
  • sdks/python/tests/test_sync_simplebox.py
  • sdks/c/src/runtime.rs
  • src/boxlite/src/rest/litebox.rs
  • apps/runner/pkg/boxlite/exec_manager_integration_test.go
  • src/cli/src/commands/serve/mod.rs
  • apps/runner/pkg/api/controllers/boxlite_exec_attach_test.go
  • apps/runner/pkg/boxlite/exec_manager.go
  • sdks/c/src/event_queue.rs
  • sdks/python/tests/test_exec_timeout_sigalrm.py
  • sdks/c/include/boxlite.h
  • sdks/c/src/exec/execution.rs
  • sdks/python/boxlite/sync_api/_simplebox.py
  • sdks/go/exec.go

@cla-assistant

cla-assistant Bot commented Jul 16, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@cla-assistant

cla-assistant Bot commented Jul 16, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ G4614
❌ Gamnaam Song


Gamnaam Song seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@G4614
G4614 force-pushed the g4614/pol-100-python-timeout-error branch from d93b470 to 4f1ab28 Compare July 16, 2026 10:25

@boxlite-agent boxlite-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📦 BoxLite review — 2 issues

Comment thread src/guest/src/service/exec/state.rs
@G4614
G4614 force-pushed the g4614/pol-100-python-timeout-error branch from c840ca4 to 3f76bc2 Compare July 16, 2026 11:02

@boxlite-agent boxlite-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📦 BoxLite review — 1 issue

Comment thread src/guest/src/service/exec/state.rs Outdated
@G4614
G4614 enabled auto-merge July 16, 2026 11:13
@G4614
G4614 force-pushed the g4614/pol-100-python-timeout-error branch 2 times, most recently from 0e16c88 to 195719a Compare July 16, 2026 11:37
@G4614
G4614 force-pushed the g4614/pol-100-python-timeout-error branch from 195719a to 9d1cdc5 Compare July 23, 2026 08:18
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