Skip to content

Isolate CliWrap startup from caller synchronization context - #25

Closed
ShutenOishi wants to merge 4 commits into
mainfrom
fix/phase8-legacy-context
Closed

ShutenOishi wants to merge 4 commits into
mainfrom
fix/phase8-legacy-context

Conversation

@ShutenOishi

@ShutenOishi ShutenOishi commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

English

The netstandard2.0 backend captures a caller's occupied SynchronizationContext during synchronous CliWrap startup. Two controlled regression tests fail before the scoped startup adapter and pass after it; startup errors still restore the caller context and remain synchronous. Modern targets are unchanged.

This is a confirmed partial fix, not resolution of the intermittent net48 completion stall. Final CI 37189457631 passed all full suites (551/554/554) but stalled in net48 stress round 27: stdin/stdout/stderr/process Tasks were all complete while the async iterator had yielded and its consumer remained pending. The failed run and artifact are preserved in the comments.

Revision 3859d4e adds bounded nested promise/awaiter decoding, verified against an owned real CLR4 fixture (int 1729, short 37, bool true), to identify the remaining transition. CI 37191060046 is pending. Local Release build has zero warnings/errors and all 29 Python checks pass. No local VSTest was run.

Keep this PR draft until a fresh all-platform CI pass and evidence review. CliWrap replacement is authorized for investigation if required; no backend replacement is claimed here. Public API and timeout/cancellation/stream ownership contracts remain unchanged. External publication remains postponed; candidate manifests are not retargeted.

日本語

.NET Standard 2.0側で呼出元の同期コンテキストに依存する起動処理を、決定的な回帰テストで確認して修正しました。起動例外の同期性と呼出元のコンテキスト復元を維持します。

一方、net48の間欠的な完了待ち停止は未解決です。CI 37189457631では通常テストがすべて成功した後、stress round 27で停止しました。下位4Taskは完了済みで、非同期列挙が値を返した後の消費側が待機しています。失敗結果と成果物はコメントに保存しています。

追加診断3859d4eは実CLR4ダンプ内の入れ子の構造体を既知値で検証し、awaiter/promiseの状態を採取します。CI 37191060046の判定待ちです。必要ならCliWrapからの移行も調査します。全CIと成果物の確認前にはマージせず、外部公開は後回しのままです。

Copy link
Copy Markdown
Owner Author

Deterministic failing baseline / 修正前の再現

Head b18a9a7b8187408a232ad4d4d6753a04b00820bd, CI 37188939390, checkout 0b293325911bdfa12d9bf70f2f879073bfe567e5, Windows job 111396844092.

Windows net48 reports exactly two failures: PsqlCompletionTests.CompleteAsync_DoesNotRequireTheStartupSynchronizationContext and ProcessRunnerTests.RunAsync_DoesNotRequireTheStartupSynchronizationContext, each with Completion required the occupied startup context; observed posts: 2. The other 549 net48 tests pass; net8/net10 each pass all 554. Caller-context restoration after a synchronous startup error passes.

Artifact 11298293450, SHA-256 c3afb4fc5b30c7bd81385754abf3c5ae105727003bbfcd7c5b30e3271daa8823, independently downloaded, digest and actual TRX failures checked. This run is a preserved failing baseline, not retried until green. It confirms the deterministic legacy context defect. The new startup adapter will be tested against the same tests and unchanged timeout/stress gates. Historical main stall evidence remains in PR #24; complete attribution of every historical stall is not claimed.

日本語: 修正前のnet48で通常実行・セッション双方が2回のPostを残して失敗し、同期コンテキスト依存を再現しました。他の549件とmodern各554件は成功。成果物のハッシュと実TRXを独立確認しました。失敗を保持し、同じテストと期限・反復条件で修正を検証します。

@ShutenOishi ShutenOishi changed the title Investigate and remove legacy execution context dependence Isolate CliWrap startup from caller synchronization context Oct 4, 2026

Copy link
Copy Markdown
Owner Author

Context fix passes its regressions, intermittent stall remains / 部分修正の限界

Head c3d53b4bb23f3f7ee00638ce677028d8d5531f4e, CI 37189457631, Windows job 111398483795: full suites pass (net48 551, net8/net10 554 each); net48 stress rounds 1–26 pass all 12 cases; round 27 aborts in the 262144-byte completion case after the unchanged watchdog. Controlled occupied-context regressions pass, so startup isolation resolves the independently proven context defect but DOES NOT resolve the intermittent stall.

Artifact 11297554452, SHA-256 a4d56daa20274368b2f22c25f7fa4c246095ef6f0d2767ea4c176d543d07fded, independently downloaded/digest checked, no raw dumps. Actual dump: stdIn/stdOut/stdErr/process task flags all 0x7000400; ExecuteAsync state 2; WhenEach iterator state -4 with its current stdout task completed. Parent completion remains pending after child EOF/drained.

PR remains Draft and is not merged. No rerun-until-green. The next coherent revision expands bounded nested promise/awaiter/context diagnostics before any additional runtime change. The earlier code revision run 37189321506 was superseded by the final documentation revision and is not completion evidence.

日本語: 同期コンテキスト依存の回帰テストは修正後に成功しましたが、26回成功後の27回目で間欠停止が再現しました。実ダンプでは4Taskが完了し、WhenEachが値をyieldした状態で上位処理が止まっています。PRはマージせず、失敗を保持して内部promise/awaiterの追加診断を行います。

Copy link
Copy Markdown
Owner Author

English

Nested-diagnostic head 3859d4e (tree 949306641028aae3bc9aa4a8a53b269583dff879), CI 37191060046 attempt 1, fails in the initial net48 full suite (44 completed, aborted), before stress. Modern full suites pass 554 each. The owned real CLR4 decoder smoke passes with Marker=1729, Token=37, Completed=True.

Artifact 11298503924 was independently downloaded; SHA-256 3a7916571d76ea7fb82626dfc318ffeb919e208b0825cd68b9772ab578e76ae3 matches and contains no raw DMP. The five-byte parent logs Complete returned without completion-finished; child EOF/drained is recorded. Actual active CliWrap state 2 has all four lower Tasks at flags 0x7000400. WhenEach state -4 has a completed stderr value; its promise version is 3 and consumer ValueTask token is 3 (matching), continueOnCapturedContext=True. The iterator uses PolyShim's internal ManualResetValueTaskSourceCore, whose state is a lazy TaskCompletionSource rather than the runtime core implementation. Pinned upstream source initializes that TCS with unsynchronized ??=, a potential producer/consumer initialization race. The capture does not expose the TCS continuation graph, so this is a source-supported hypothesis, not a demonstrated root cause.

Do not rerun this failure or merge the partial fix. Maintainer authorizes evaluating CliWrap replacement. A separate isolated prototype will reuse the existing Process lifecycle with narrow legacy argument/exit/tree compatibility, preserve the bounded input bridge and public contracts, and be tested under a superseding ADR if adopted. Publication remains postponed.

日本語

追加診断のCIでも通常net48テスト中に5バイトの完了待ちが停止しました。実CLR4の構造体読み取り自己検証は成功し、成果物hash・生ダンプ不在を独立確認しました。下位4Taskは正常完了、列挙は値を返した状態で、promiseと消費側tokenは同じ3です。互換promiseの遅延TCS生成に同期がなく、競合の可能性を一次ソースで確認しましたが、継続グラフは未取得で原因断定はしません。失敗を再試行せず保持し、CliWrapを外す別案を独立した作業領域で試作・検証します。公開延期を保持します。

Copy link
Copy Markdown
Owner Author

English

Superseded by ADR-0024 / merged PR #26. Replacement main d66a1e2 passed exact-main CI37194612585, all18 jobs at attempt1; actual Windows 30/3/3 stress/native/Linux artifacts independently verified in PR26's final receipt. Closing this unmerged partial fix while retaining its deterministic baseline and failed stress/nested diagnostic evidence and branch.

日本語

ADR-0024/PR #26のProcess置換により、この部分修正は未マージで閉じます。置換mainの全18CIと実成果物を確認済みです。修正前・反復停止・追加診断の失敗記録とブランチは保持します。

@ShutenOishi ShutenOishi closed this Oct 4, 2026
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