From 7f5dcc452a8bee29def7f449037aa2f340a0991a Mon Sep 17 00:00:00 2001 From: leroyomey <180032997+leroyomey@users.noreply.github.com> Date: Fri, 9 Oct 2026 16:31:04 -0600 Subject: [PATCH] fix(win): don't close the pseudoconsole twice on a second kill() --- src/win/conpty.cc | 9 ++++++--- src/windowsTerminal.test.ts | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/win/conpty.cc b/src/win/conpty.cc index 931c5362d..ac45e9666 100644 --- a/src/win/conpty.cc +++ b/src/win/conpty.cc @@ -495,7 +495,7 @@ static Napi::Value PtyResize(const Napi::CallbackInfo& info) { std::lock_guard lock(g_ptyHandlesMutex); const pty_baton* handle = get_pty_baton(lock, id); - if (handle != nullptr) { + if (handle != nullptr && handle->hpc != nullptr) { HANDLE hLibrary = LoadConptyDll(info, useConptyDll); bool fLoadedDll = hLibrary != nullptr; if (fLoadedDll) @@ -537,7 +537,7 @@ static Napi::Value PtyClear(const Napi::CallbackInfo& info) { std::lock_guard lock(g_ptyHandlesMutex); const pty_baton* handle = get_pty_baton(lock, id); - if (handle != nullptr) { + if (handle != nullptr && handle->hpc != nullptr) { HANDLE hLibrary = LoadConptyDll(info, useConptyDll); bool fLoadedDll = hLibrary != nullptr; if (fLoadedDll) @@ -577,9 +577,12 @@ static Napi::Value PtyKill(const Napi::CallbackInfo& info) { PFNCLOSEPSEUDOCONSOLE const pfnClosePseudoConsole = (PFNCLOSEPSEUDOCONSOLE)GetProcAddress( (HMODULE)hLibrary, useConptyDll ? "ConptyClosePseudoConsole" : "ClosePseudoConsole"); - if (pfnClosePseudoConsole) + if (pfnClosePseudoConsole && handle->hpc != nullptr) { pfnClosePseudoConsole(handle->hpc); + // The handle stays in ptyHandles until the exit watcher erases it, so + // null hpc to keep a later call from using the closed pseudoconsole. + handle->hpc = nullptr; } } // Defensive: if PtyConnect was never called (or failed before closing the diff --git a/src/windowsTerminal.test.ts b/src/windowsTerminal.test.ts index c76196512..ffccf0a9b 100644 --- a/src/windowsTerminal.test.ts +++ b/src/windowsTerminal.test.ts @@ -101,6 +101,13 @@ if (process.platform === 'win32') { term.on('exit', () => done()); term.kill(); }); + it('should not crash parent process when killed twice', function (done) { + this.timeout(20000); + const term = new WindowsTerminal('cmd.exe', [], { useConptyDll }); + term.on('exit', () => done()); + term.kill(); + term.kill(); + }); it('should kill the process tree', function (done: Mocha.Done): void { this.timeout(20000); const term = new WindowsTerminal('cmd.exe', [], { useConptyDll });