Gateway

Gateway ロック

理由

  • 1 つの状態ディレクトリを所有できる Gateway プロセスは 1 つだけです。追加の Gateway は、分離されたプロファイル、状態ディレクトリ、設定、ポートを使用して実行します。
  • 古いロックファイルを残さずに、クラッシュや SIGKILL に耐えます。
  • 別の Gateway がすでにポートを所有している場合は、明確なエラーですぐに失敗します。

3 つのレイヤー

起動時には、次の 3 つの手順を順番に実行して所有権を強制します。

  1. 状態所有権ロックは、正規化された状態ディレクトリをキーとするロックを取得します。OPENCLAW_ALLOW_MULTI_GATEWAY=1で起動した Gateway を含むすべての Gateway が対象となるため、破壊的な SQLite メンテナンスが稼働中の所有者と競合することはありません。
  2. 設定ロックは、従来の設定ごとのロックを取得し、ランタイムポートを記録します。複数 Gateway モードでは、この設定シングルトンをスキップしますが、状態所有権ロックは維持します。
  3. ソケットバインドは、HTTP/WebSocket リスナー(デフォルトは ws://127.0.0.1:18789)を排他的な TCP リスナーとしてバインドします。

各レイヤーは個別に失敗する可能性があり、それぞれ固有の GatewayLockError をスローします。

状態ロックと設定ロック

  • ロックの生存確認には、記録された PID、利用可能な場合はプラットフォームのプロセス開始 ID、および Gateway プロセス ID が使用されます。検証済みの所有者は、そのポートがリッスンを開始する前の起動中も正式な所有者として扱われます。

  • 専用の SQLite コーディネーターが、メタデータの検査、古い所有者の回収、ロックの置換を直列化します。その排他トランザクションは、所有プロセスがクラッシュすると自動的に解放されます。

  • ロックファイルが存在しない場合、または記録された所有プロセスが終了している場合、起動処理はロックを回収して続行します。

  • いずれかのロックが現在保持されている場合、起動処理は断念するまで最大 5 秒間(デフォルト)再試行します。

    text
    GatewayLockError("Gateway はすでに実行中です(pid <pid>)。<ms>ms 後にロックがタイムアウトしました")

ソケットバインド

  • EADDRINUSEの場合、直前に終了したプロセスによる TIME_WAIT の期間を乗り切るため、起動処理は 500ms 間隔で最大 20 回(合計約 10 秒)バインドを再試行します。

  • 再試行後もポートが使用中の場合:

    text
    GatewayLockError("別の Gateway インスタンスがすでに ws://127.0.0.1:<port> でリッスンしています")
  • その他のバインドエラー:

    text
    GatewayLockError("ws://127.0.0.1:<port> で Gateway ソケットをバインドできませんでした: <cause>")

シャットダウン時に、Gateway は HTTP/WebSocket サーバーを閉じ、状態ロックファイルと 設定ロックファイルを削除します。

運用上の注意

  • 別の Gateway 以外のプロセスがポートを占有している場合も、エラーは同じです。ポートを解放するか、openclaw gateway --port <port>で別のポートを選択してください。
  • OPENCLAW_ALLOW_MULTI_GATEWAY=1では複数の設定/ランタイムインスタンスを使用できますが、可変状態を共有することはできません。各インスタンスには引き続き一意の OPENCLAW_STATE_DIR が必要です。
  • サービススーパーバイザーの管理下では、上記いずれかのエラーが発生した新しい Gateway プロセスは、まず既存のプロセス上の /healthz を調査します。そのプロセスが正常であれば、新しいプロセスは失敗せず、既存のプロセスに制御を委ねます。systemd では、終了コード 78 で終了します。ユニットの RestartPreventExitStatus=78 により、Restart=always がロックまたは EADDRINUSE の競合でループするのを防ぎます。既存のプロセスが正常にならない場合、ヘルスプローブの再試行は制限時間内で終了し、その後、起動処理は無限にループせず、上記のロックエラーで失敗します。
  • macOS アプリは Gateway を起動する前に独自の軽量な PID ガードを使用しますが、実際のランタイム強制を行うのは上記のファイルロックとソケットバインドです。

関連項目

Was this useful?
On this page

On this page