fix: make stdio redirection scoped and exception-safe - #243
fix: make stdio redirection scoped and exception-safe#243Ayoubbelguellaoui wants to merge 9 commits into
Conversation
c522e25 to
6bdc310
Compare
|
Thank you for your contribution! However, does this PR have any overlapping parts with #236? |
6bdc310 to
0fc270b
Compare
|
There is some overlap at the step-execution/runtime level, particularly around EngineFlow and failure cleanup, but the two PRs address different issues. PR #236 focuses on containing tool failures, persisting Incomplete, interrupted-operation recovery, and terminal failure state propagation. This PR focuses specifically on making process-global stdout/stderr redirection scoped and exception-safe, isolating concurrent redirects, and guaranteeing runtime operation cleanup when event publishing fails. The overlap is therefore limited to the surrounding execution/cleanup paths; the implementations address separate failure modes. |
Got it, I just merged #236. Could you rebase and resolve the conflicts? |
0fc270b to
4e47409
Compare
|
Hi @Ayoubbelguellaoui , I’d like to ask why this PR was closed. Is there anything we can help with? |
|
just for making sur that is work good , thanks i will reopen it |
0d5d3bd to
c5d51ac
Compare
c5d51ac to
1517ffa
Compare
d4c3cf2 to
6ed53e8
Compare
|
@Ayoubbelguellaoui Is this PR ready to be merged? |
|
yes it's ready |
Emin017
left a comment
There was a problem hiding this comment.
P2 - Close the process-level redirect created by init_api_runtime_log
At this line, _StdioRedirect.__enter__() saves dup(1)/dup(2), but the instance is immediately discarded. Since _restore() is only reached through close()/__exit__(), every call leaks two file descriptors and there is no handle to restore or replace the previous redirect. Repeated initialization on the same process grows the fd count (8 -> 10 -> 12 in a local check). Please retain a process-owned handle and close the previous redirect before reinitializing, and add a repeated-init cleanup test.
Emin017
left a comment
There was a problem hiding this comment.
The previous step-log failure-summary issue is fixed, but the new capture error path introduces a blocking execution regression. Please address the inline finding before merging.
|
fixed ! |
Emin017
left a comment
There was a problem hiding this comment.
The previous exception-escape regression is addressed, but the latest fixes still leave two blocking execution/ownership regressions. Please address the inline findings before merging.
| except (Exception, SystemExit) as exc: | ||
| step_error = record_tool_failure(workspace.logger, step_tag, exc) | ||
| with capture_stdio_to_file(log_file) as capture_ok: | ||
| if not capture_ok: |
There was a problem hiding this comment.
P1: Do not skip tool execution when log capture fails
When capture_ok is false, this branch sets step_error and bypasses run_step() entirely. AgentEngineFlow now does the same. A step-log path is an observability output, not a prerequisite for running the EDA tool; the base revision logged the redirection failure and still invoked the tool. With workspace_step.log.file pointing to a directory and the tool/check mocks returning success, I changed the new regression tests to require those mocks to be called: both the Agent and standard EngineFlow cases fail because neither tool function runs. The added tests currently only expect Incomplete and never assert that the mocks were invoked, so they encode this regression as the desired behavior.
Please keep tool execution independent of whether capture setup succeeds (logging the capture failure through the remaining usable channel), then determine the step state from the real tool result and outputs. Add call assertions to both unusable-log-path tests so a logging failure cannot silently cancel implementation work.
| "operation.completed", | ||
| {"result": result}, | ||
| ) | ||
| self._cleanup_workspace_active(operation_id) |
There was a problem hiding this comment.
P1: Make the terminal transition and active-owner cleanup atomic, with a finally fallback
This cleanup runs only after the lock that records succeeded has been released. A polling client can therefore observe the terminal state and immediately call start(), but still receive RuntimeOperationConflict because _active_by_workspace points to the completed operation. I reproduced this deterministically by blocking _cleanup_workspace_active() after the terminal state was written: operation_status() returned succeeded, while the next operation for the same workspace was rejected.
Moving cleanup out of the outer finally also loses the previous guarantee for uncaught BaseExceptions. A runner that raises SystemExit now leaves the workspace permanently present in shutdown_barrier() and blocks all later operations; the same test passes on the base revision. Please remove the active mapping in the same critical section that publishes the terminal state, and retain guaranteed cleanup in finally for exits that do not produce a normal terminal event. Add regression tests for both the terminal-state/start race and a runner SystemExit.
What Changed
Updated chipcompiler/engine/flow.py, chipcompiler/engine/rerun.py, and agent/engine.py to ensure step-level log redirects close cleanly.
Updated chipcompiler/runtime/operations.py to treat event publisher exceptions as non-fatal and wrapped active operation tracking in finally blocks to guarantee cleanup.
Added and updated tests in test/cli/rendering/test_progress.py, test/runtime/test_events.py, and test/runtime/test_operations.py to cover stdio restoration, thread isolation under concurrency, and resilient operation tracking.
Scope
Select the areas touched by this PR:
uv.lock, or release artifacts.Runtime And Packaging Impact
ecc-toolsorecc-dreamplacedependency changedNotes:
Validation
List the commands you ran. Mark checks that are not applicable as N/A.
uv run pytest test/uv run ruff check chipcompiler testuv run ruff format --check chipcompiler testecc --help,ecc --version,ecc version --jsonnix run .#cli -- --helpuv run pytest test/— 1460 passed, 8 skipped, 4 xfailed, 2 environment-related failures.Skipped checks and reason:
Checklist