fix: git 実行のスレッド枯渇デッドロックを根治し終了ハング・表示凍結を解消#78
Draft
sasagar wants to merge 1 commit into
Draft
Conversation
GitRunner/GitHubEngine は git/gh 1 回ごとにグローバルキューのワーカーを waitUntilExit + group.wait でブロックし、stdout/stderr の読み取りブロックを 同じプールへ投入していた。並行実行が重なると GCD プール(ソフト上限 64)が 「待つ側」で埋まり、「読む側」が永遠にスケジュールされないスターベーション・ デッドロックに陥る。この状態では全 git 操作が凍結して差分/履歴/ブランチ表示が 更新されず、終了時も AppKit のウィンドウ状態保存が実行できず _waitForPendingChangesToFinish でハングして強制終了に至っていた (org ディレクトリを開いた際の一斉 refresh で発生しやすい)。 - ProcessRunner.run(async)を新設: posix_spawn + DispatchSource(read/proc) + waitpid の完全非同期実装で、待機中にスレッドを一切占有しない。 NOTE_EXIT の登録レース(登録完了前に子が exit すると発火しない)は registration handler での再チェックと 500ms の WNOHANG フォールバックで回収 - GitRunner / GitHubEngine のプロセス実行を ProcessRunner.run へ委譲 - GitRunner に同時実行ゲート(ConcurrencyGate, 上限 16)を追加し、 org ディレクトリを開いた直後の git プロセス一斉起動を抑制 - AgentStatusBus の accept() 待ちを GCD キューから専用スレッドへ移し、 常駐分のプール消費を排除
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
症状
根本原因
GitRunner.run/GitHubEngine.runは git/gh 1 回ごとにグローバルキューのワーカーをwaitUntilExit()+group.wait()でブロックし、stdout/stderr の読み取りブロックを同じプールへ投入していた。並行実行が重なると GCD プール(ソフト上限 64)が「待つ側」で埋まり、「読む側」が永遠にスケジュールされないスターベーション・デッドロックに陥る。LaboLabo_2026-07-07-123946.hang)で確認: 64 スレッド全部がGitRunner.swift:57のgroup.wait()で停止、レポートにProcesses reached dispatch thread soft limit (64)の明記ありNSPersistentUIManager _waitForPendingChangesToFinishで永久待ち → 強制終了(症状1)修正
ProcessRunner.run(async)を新設:posix_spawn+ DispatchSource(read/proc) +waitpidの完全非同期実装。待機中にスレッドを 1 本も占有しないterminationHandler/readabilityHandlerベースの実装は、並行実行の負荷後に別 NSTask の終了通知が届かなくなる現象を macOS 26.5 で起こしたため不採用GitRunner/GitHubEngineをProcessRunner.runへ委譲(同型バグの重複を解消)ConcurrencyGate(上限 16) で git の同時プロセス数を抑制AgentStatusBusのaccept()待ちを GCD キューから専用スレッドへ移し、セッション数ぶんの常駐プール消費を排除テスト / 検証
swift test全 98 テスト成功dispatch_group_waitで停止するのをサンプラで観測)未検証