Skip to content

fix(pty): the Windows kill reports success as failure, and the caller drops it #96

Description

@smileygames

観測

portable-pty-patch/src/win/mod.rs の kill 経路が、TerminateProcess の戻り値を逆に解釈している。

fn do_kill(&mut self) -> IoResult<()> {
    let proc = self.proc.lock().unwrap().try_clone().unwrap();
    let res = unsafe { TerminateProcess(proc.as_raw_handle() as _, 1) };
    let err = IoError::last_os_error();
    if res != 0 {
        Err(err)      // TerminateProcess は成功で非ゼロを返す
    } else {
        Ok(())        // ゼロが失敗である
    }
}

Win32 の TerminateProcess は成功で非ゼロ、失敗でゼロを返す。このコードは成功したときに Err(last_os_error()) を返し、失敗したときに Ok(()) を返す。

同じ反転が WinChildKiller::kill(同ファイル)にもある。

今それが表に出ていない理由

WinChild::kill が結果を握り潰している。

impl ChildKiller for WinChild {
    fn kill(&mut self) -> IoResult<()> {
        self.do_kill().ok();
        Ok(())
    }
}

src-tauri/src/pty.rsPtyInstance.childBox<dyn portable_pty::Child + Send> であり、ChildChildKiller を継承する。したがって pty.child.kill() はこの WinChild::kill に解決し、常に Ok(()) を返す

結果として:

プロセスが実際に落ちることは実機で確認済みである(2026-08-25、AI が操作)。cmd.exe とその孫の claude.exe が両方消えることを PID で確認した。木が落ちるのは TerminateProcess ではなく、PtyInstance が drop されて killer: Box<dyn MasterPty> が閉じ、ConPTY に繋がったプロセスが道連れになる経路による。したがってこの反転は現状の動作を壊していない。壊しているのは、失敗を報告する能力そのものである。

なぜ直すか

kill が失敗しうる経路(ハンドルが無効、権限が無い、既に終了している)で、呼び出し側は成功と区別できない。#85 はアプリ終了時に一括で kill する経路を入れたが、その失敗を検出する手段が無いため、孤児が残った場合でも黙って閉じる。

未決

  • 反転を直すだけにするか、WinChild::kill の握り潰しも解くか。 反転だけ直すと do_kill は正しくなるが .ok() が捨てているため呼び出し側からは何も変わらない。握り潰しも解くと、kill_ptykill_all の既存のエラー経路が初めて生きる——ただし「既に終了しているプロセスへの kill」が失敗として上がってくるようになるため、その扱いを決める必要がある。
  • vendored patch を直すか、上流へ出すか。 portable-pty-patch/ はこのリポジトリが抱えている改変版である。ローカルで直すと上流との差分が増える。

対象ファイル

  • portable-pty-patch/src/win/mod.rs
  • src-tauri/src/pty.rs — 握り潰しを解く場合、呼び出し側の扱い
  • docs/0-requirements.md — 失敗の扱いを記述する場合

関連

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug動いていない、壊れているforming本文を再構築しながら要求を整えている状態

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions