Skip to content

原文(日本語訳)

セッション終了後にプロセスがハングする問題を修正しました。

原文(英語)

Fixed process hanging after session close

概要

Claude Code 2.1.39では、セッションを終了した後もClaude Codeのプロセスが終了せずにハングし続ける問題が修正されました。この修正により、リソースの適切な解放とクリーンなプロセス終了が保証され、システムリソースの無駄な消費が防止されます。

発生していた問題

症状

  • セッション終了(/exitCtrl+Dquit)後もプロセスが残留
  • ターミナルを閉じてもバックグラウンドプロセスが動作し続ける
  • 複数のゾンビプロセスが蓄積
  • システムリソース(メモリ、ファイルディスクリプタ)のリーク

影響

bash
# 修正前: セッション終了後もプロセスが残る
claude
# ... セッションを終了
/exit

# ターミナルは終了するが、プロセスは残る
ps aux | grep claude
# user  12345  0.5  2.3 1234567 234567 ?  S  10:00  0:15 claude
# user  12346  0.3  1.8 1234567 234567 ?  S  10:05  0:10 claude
# user  12347  0.4  2.1 1234567 234567 ?  S  10:10  0:12 claude

実践例

正常な終了プロセス(修正後)

bash
# Claude Codeを起動
claude

# 作業を実施
# "Refactor the authentication module"

# セッションを終了
/exit

# 確認: プロセスが完全に終了している
ps aux | grep claude
# (何も表示されない)

echo $?
# 0(正常終了)

Ctrl+Dでの終了

bash
claude

# Ctrl+D を押す
^D

# プロセスが即座に終了
# Goodbye! Session ended.

ps aux | grep claude
# (プロセスなし)

シグナルによる終了

bash
# Claude Code実行中の別ターミナルから

# プロセスIDを取得
PID=$(pgrep -f claude)

# SIGTERMシグナルを送信
kill -TERM $PID

# 修正前: プロセスがハング
# 修正後: グレースフルシャットダウン
# Received SIGTERM. Saving session and exiting...
# Session saved to: ~/.claude/sessions/auto-save-12345.json
# Goodbye!

# プロセスが完全に終了
ps -p $PID
# (プロセスが見つからない)

強制終了が必要なケース

bash
# 応答しないセッションの強制終了

# 修正前: SIGKILL が必要だった
kill -9 $PID

# 修正後: SIGTERM で十分
kill -TERM $PID
# または
claude --kill-all  # すべてのClaude Codeプロセスを安全に終了

リソース管理の改善

メモリリークの防止

bash
# 長時間セッション後の終了

# 修正前:
# - メモリが解放されない
# - スワップが発生
# - システムが重くなる

# 修正後:
# - すべてのリソースが適切に解放
# - メモリ使用量が即座に低下

ファイルディスクリプタのクリーンアップ

bash
# 開いているファイルディスクリプタの確認
lsof -p $(pgrep claude)

# 修正前(終了後):
# claude  12345 user  10r  REG  /tmp/session.lock
# claude  12345 user  11w  FIFO pipe
# claude  12345 user  12r  DIR  /home/user/project
# (ファイルが開いたまま)

# 修正後(終了後):
# (すべてのファイルが閉じられる)

ネットワーク接続のクローズ

bash
# アクティブな接続の確認
netstat -anp | grep claude

# 修正前(終了後):
# tcp  0  0  127.0.0.1:54321  52.85.161.44:443  ESTABLISHED  12345/claude
# (接続が残る)

# 修正後(終了後):
# (すべての接続がクローズ)

バックグラウンドタスクの処理

Agent Teams利用時

bash
# Agent Teamsを使用したセッション
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
claude

# "Create a team of 5 agents for parallel refactoring"

# 修正前の終了:
# - メインセッションは終了
# - バックグラウンドのエージェントプロセスが残る

# 修正後の終了:
/exit
# Shutting down 5 agent team members...
# Agent 1: Saved and exited
# Agent 2: Saved and exited
# Agent 3: Saved and exited
# Agent 4: Saved and exited
# Agent 5: Saved and exited
# All agents terminated successfully
# Goodbye!

MCPサーバーの切断

bash
# MCP接続を使用したセッション
claude mcp add puppeteer

claude
# MCPツールを使用した作業

/exit

# 修正後:
# Disconnecting from MCP servers...
#   ✓ puppeteer server disconnected
# All MCP connections closed
# Goodbye!

自動クリーンアップスクリプト

システムサービスとして実行する場合

bash
# systemd サービスファイル
# /etc/systemd/system/claude-code-cleanup.service

[Unit]
Description=Claude Code Cleanup Service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/claude-cleanup.sh

[Install]
WantedBy=multi-user.target
bash
#!/bin/bash
# /usr/local/bin/claude-cleanup.sh

# 孤立したClaude Codeプロセスをクリーンアップ
ORPHANED=$(ps aux | grep -E 'claude.*--session' | grep -v grep | awk '{print $2}')

if [ -n "$ORPHANED" ]; then
  echo "Cleaning up orphaned processes: $ORPHANED"
  kill -TERM $ORPHANED
  sleep 5

  # まだ残っている場合は強制終了
  REMAINING=$(ps aux | grep -E 'claude.*--session' | grep -v grep | awk '{print $2}')
  if [ -n "$REMAINING" ]; then
    kill -9 $REMAINING
  fi
fi

Cron ジョブでの定期クリーンアップ

bash
# crontab -e
# 1時間ごとに孤立プロセスをチェック
0 * * * * /usr/local/bin/claude-cleanup.sh

モニタリングとアラート

プロセス監視スクリプト

python
#!/usr/bin/env python3
# monitor-claude-processes.py

import psutil
import time
from datetime import datetime

THRESHOLD_MINUTES = 60

def check_zombie_processes():
    for proc in psutil.process_iter(['pid', 'name', 'create_time', 'status']):
        try:
            if 'claude' in proc.info['name'].lower():
                runtime = time.time() - proc.info['create_time']
                runtime_minutes = runtime / 60

                if proc.info['status'] == psutil.STATUS_ZOMBIE:
                    print(f"WARNING: Zombie process detected!")
                    print(f"  PID: {proc.info['pid']}")
                    print(f"  Runtime: {runtime_minutes:.1f} minutes")

                elif runtime_minutes > THRESHOLD_MINUTES:
                    print(f"INFO: Long-running process")
                    print(f"  PID: {proc.info['pid']}")
                    print(f"  Runtime: {runtime_minutes:.1f} minutes")
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass

if __name__ == "__main__":
    check_zombie_processes()

注意点

  • グレースフル シャットダウン: 強制終了(SIGKILL)ではなく、通常の終了(SIGTERM)を使用することで、セッションが保存されます
  • 保存されていない作業: 終了前に作業が自動保存されますが、重要な変更は明示的にコミットすることをお勧めします
  • 長時間実行タスク: バックグラウンドで長時間実行されるタスクがある場合は、完了を待つか、明示的にキャンセルしてください
  • リソース制限: システムのリソース制限(ulimit)が適切に設定されていることを確認してください

トラブルシューティング

ハングしたプロセスの特定

bash
# Claude Codeプロセスの状態確認
ps aux | grep claude | grep -v grep

# プロセスのスレッド状態確認
ps -eLf | grep claude

# スタックトレースの取得
sudo gdb -p <PID>
(gdb) thread apply all bt
(gdb) quit

強制終了が必要な場合

bash
# すべてのClaude Codeプロセスを強制終了
pkill -9 -f claude

# 特定のセッションのみ終了
kill -9 $(pgrep -f "claude.*--session-id=abc123")

ログの確認

bash
# 終了ログの確認
tail -f ~/.claude/logs/shutdown.log

# 異常終了のログ
grep "abnormal" ~/.claude/logs/shutdown.log
grep "hang" ~/.claude/logs/shutdown.log

関連情報