Skip to content

fix: 孤児 VS Code IPC ソケットで devbase up --open が ECONNREFUSED になる問題を修正 - #100

Merged
takemi-ohama merged 1 commit into
mainfrom
fix/vscode-ipc-socket-connect-check
Aug 19, 2026
Merged

fix: 孤児 VS Code IPC ソケットで devbase up --open が ECONNREFUSED になる問題を修正#100
takemi-ohama merged 1 commit into
mainfrom
fix/vscode-ipc-socket-connect-check

Conversation

@takemi-ohama

Copy link
Copy Markdown
Contributor

概要

devbase up が次のエラーで失敗する報告を受けての修正です。

Unable to connect to VS Code server: Error in request.
Error: connect ECONNREFUSED /var/folders/.../T/vscode-ipc-8d9a04ee-....sock
at PipeConnectWrap.afterConnect [as oncomplete] (node:net:1706:16) {
errno: -61, code: 'ECONNREFUSED', syscall: 'connect',
}

#97VSCODE_IPC_HOOK_CLI実在確認を入れましたが、ソケットの死に方は 2 通りあり、実在確認では片方しか弾けていませんでした。

状態起きる場面os.path.exists()従来の判定
ファイルごと消えているVS Code のウィンドウを正常に閉じたFalse正しく dead
ファイルは残るが listen していないVS Code のクラッシュ・強制終了・OS 再起動True誤って alive

後者は $TMPDIR に孤児ソケットとして溜まり、ls では生きているものと区別が付きません。これを in_vscode=True と誤判定して code を IPC 経由で叩くため、ECONNREFUSED で失敗していました。

報告環境の実測でも、エラーに出ている 8d9a04ee はファイルとしては存在する一方で接続は拒否されており、同じ $TMPDIR に生きているソケットと孤児が混在していました。

ALIVE vscode-ipc-1d673626-....sock
DEAD vscode-ipc-846482f8-....sock (Errno 61 Connection refused)
DEAD vscode-ipc-8d9a04ee-....sock (Errno 61 Connection refused) ← エラーに出たもの
ALIVE vscode-ipc-8dd26478-....sock

変更点

  • _ipc_socket_alive()connect ベースに変更(AF_UNIX / タイムアウト 0.5 秒)。ENOENT / ECONNREFUSED / EACCES / ENOTSOCK / パス長超過(ValueError)をまとめて「使えない」と扱う
  • AF_UNIX が無いプラットフォームでは従来どおり実在確認へフォールバック
  • 警告文を「存在しません」→「接続できません」に改め、ファイルが残っていても接続を拒否する場合があることを明記
  • 回帰テストを追加(孤児ソケット / ソケットですらない通常ファイル)。既存の in_vscode テストは通常ファイルではなく実際に listen する AF_UNIX ソケットを使うよう修正
  • docs/user/environment-variables.md にソケットの死に方 2 通りを追記。tmux 追随フックの -S guard も孤児ソケットを検出できない点を注記
  • CHANGELOG に Fixed エントリを追加

タイムアウトを 0.5 秒にしたのは、生きていれば UNIX ドメインソケットの接続は即座に完了し、up の最後に走る処理なので体感を優先したためです。

動作確認

  • uv run pytest1234 件 green(新規テスト 2 件を含む)
  • ruff check --select=E9,F63,F7,F82 lib(CI と同じ引数)— All checks passed
  • python -m compileall -q lib bin(CI と同じ)— OK
  • 報告環境の実ソケットに対して _ipc_socket_alive を実行し、孤児(存在するが listen なし)→ False、生存 → True を確認
  • 孤児ソケットを指した状態で open_editor を実行し、警告が出たうえで IPC を使わない通常の code --folder-uri 起動へ落ちることを確認(ローカル端末では launch、SSH 経路では従来どおり print_command へ degrade)

回避策(このPRのマージ前)

孤児ソケットを掃除するか、変数を生きているソケットへ張り替えれば回避できます。

# 孤児ソケットだけを削除(生きているものは残す)
python3 - <<'PY'import glob, os, socketfor p in glob.glob(os.path.join(os.environ.get("TMPDIR", "/tmp"), "vscode-ipc-*.sock")): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM); s.settimeout(0.5) try: s.connect(p) except OSError: os.unlink(p); print("removed", p) finally: s.close()PY

PR #97 で VSCODE_IPC_HOOK_CLI の実在確認を入れたが、ソケットの死に方には
「ファイルごと消えている」ほかに「ファイルは残っているが listen しているプロセスが
居ない」の 2 通りがある。後者は VS Code のクラッシュ・強制終了・OS 再起動で後始末
されなかった場合に $TMPDIR へ孤児として残り、os.path.exists() では弾けない。
その結果 in_vscode=True と誤判定して code を IPC 経由で起動し、
Unable to connect to VS Code server: Error in request.
Error: connect ECONNREFUSED .../vscode-ipc-<uuid>.sock
で失敗していた。
- _ipc_socket_alive() を connect ベースに変更 (AF_UNIX / タイムアウト 0.5 秒)。
ENOENT / ECONNREFUSED / EACCES / ENOTSOCK / パス長超過をまとめて「使えない」と扱う
- AF_UNIX が無いプラットフォームでは従来どおり実在確認へフォールバック
- 警告文を「存在しません」から「接続できません」に改め、ファイルが残っていても
接続を拒否する場合があることを明記
- 孤児ソケット / 通常ファイルのケースを回帰テストに追加。既存の in_vscode テストは
実際に listen する AF_UNIX ソケットを使うよう修正
- docs にソケットの死に方 2 通りを追記。tmux 追随フックの -S guard も孤児ソケットを
検出できない点を注記
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01622CAKyYfonYuZ6AqRJvDg
@takemi-ohama
takemi-ohama merged commit 2906ccf into mainAug 19, 2026
5 checks passed
@takemi-ohama
takemi-ohama deleted the fix/vscode-ipc-socket-connect-check branch August 19, 2026 15:33
takemi-ohama added a commit that referenced this pull request Aug 19, 2026
PR #100 で devbase 側の判定は connect ベースにしたが、docs が配っている tmux
プロンプトフックのサンプルは `test -S` のままだった。-S はファイルの種別しか見ない
ため、VS Code の異常終了で残った listen していない孤児ソケットも通過してしまい、
フックが tmux show-environment からの拾い直しを早期 return でスキップする。
その結果、tmux セッション環境には生きたソケットが入っているのに、すでに動いている
ペインのシェルだけが古い値を持ち続け、`devbase up --open` が毎回「手元で実行する
コマンドの提示」へ degrade していた(実機で再現を確認)。
- サンプルの guard に `nc -U -w 1 <sock> </dev/null` による接続確認を追加。
macOS の nc は -z を付けると Unix ドメインソケットで誤判定するため付けない
(生存ソケットで rc=1 になることを実測)
- -S を前段に残し、ソケットファイルが無い一般ケースでは nc を起動しないままにする
- 孤児ソケットは ls でも test -S でも見分けが付かない旨を本文に明記
- CHANGELOG に Fixed エントリを追加
Claude-Session: https://claude.ai/code/session_01622CAKyYfonYuZ6AqRJvDg
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto 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

@takemi-ohama