Skip to content

Commit 1e0f316

Browse files
committed
fix: in windows terminal can be closed with running commands and tab name display wrong
1 parent 88d7a69 commit 1e0f316

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

src-node/terminal.js

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const pty = require("node-pty");
2222
const os = require("os");
2323
const path = require("path");
2424
const which = require("which");
25+
const {execFile} = require("child_process");
2526
const NodeConnector = require("./node-connector");
2627

2728
const CONNECTOR_ID = "phoenix_terminal";
@@ -146,6 +147,7 @@ exports.createTerminal = async function ({id, shell, args, cwd, cols, rows, env}
146147

147148
terminals[id] = {
148149
pty: ptyProcess,
150+
shellPath: shell,
149151
buffer: "",
150152
flushTimer: null,
151153
paused: false
@@ -341,6 +343,65 @@ exports.getDefaultShells = async function () {
341343
return {shells};
342344
};
343345

346+
/**
347+
* On Windows, node-pty's .process returns the terminal name (e.g. "xterm-256color")
348+
* instead of the actual foreground process. This helper queries the process tree
349+
* via PowerShell's Get-CimInstance to find the deepest child process name.
350+
* Falls back gracefully if PowerShell is unavailable or returns unexpected output.
351+
* @param {number} pid - The shell PID to look up children for
352+
* @returns {Promise<string>} The leaf child process name, or empty string
353+
*/
354+
function _getWindowsForegroundProcess(pid) {
355+
return new Promise((resolve) => {
356+
const psCommand = `Get-CimInstance Win32_Process -Filter 'ParentProcessId=${pid}'` +
357+
` | Select-Object Name,ProcessId | ConvertTo-Json -Compress`;
358+
let settled = false;
359+
function done(val) {
360+
if (!settled) {
361+
settled = true;
362+
resolve(val);
363+
}
364+
}
365+
366+
// Hard 2-second deadline — don't block the UI waiting for PowerShell
367+
const deadline = setTimeout(() => done(""), 2000);
368+
369+
let child;
370+
try {
371+
child = execFile("powershell.exe", [
372+
"-NoProfile", "-NoLogo", "-Command", psCommand
373+
], {timeout: 2000, windowsHide: true}, (err, stdout) => {
374+
clearTimeout(deadline);
375+
if (err || !stdout || !stdout.trim()) {
376+
done("");
377+
return;
378+
}
379+
try {
380+
let parsed = JSON.parse(stdout.trim());
381+
// PowerShell returns a single object if one result, an array if multiple
382+
if (!Array.isArray(parsed)) {
383+
parsed = [parsed];
384+
}
385+
const leaf = parsed.length > 0 ? parsed[parsed.length - 1] : null;
386+
done(leaf && typeof leaf.Name === "string" ? leaf.Name : "");
387+
} catch (e) {
388+
done("");
389+
}
390+
});
391+
} catch (e) {
392+
// powershell.exe not found or execFile threw synchronously
393+
clearTimeout(deadline);
394+
done("");
395+
return;
396+
}
397+
398+
child.on("error", () => {
399+
clearTimeout(deadline);
400+
done("");
401+
});
402+
});
403+
}
404+
344405
/**
345406
* Get foreground process info for a terminal
346407
* @param {Object} params
@@ -352,9 +413,23 @@ exports.getTerminalProcess = async function ({id}) {
352413
if (!term) {
353414
throw new Error(`Terminal ${id} not found`);
354415
}
416+
417+
// On Mac/Linux, node-pty .process returns the actual foreground process name
418+
if (process.platform !== "win32") {
419+
return {
420+
process: term.pty.process,
421+
pid: term.pty.pid
422+
};
423+
}
424+
425+
// On Windows, resolve the actual process from the PID tree
426+
const shellPid = term.pty.pid;
427+
const childName = await _getWindowsForegroundProcess(shellPid);
428+
// If a child process exists, return it; otherwise return the shell executable name
429+
const processName = childName || path.basename(term.shellPath || "");
355430
return {
356-
process: term.pty.process,
357-
pid: term.pty.pid
431+
process: processName,
432+
pid: shellPid
358433
};
359434
};
360435

src/extensionsIntegrated/Terminal/main.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ define(function (require, exports, module) {
5757
const SHELL_NAMES = new Set([
5858
"bash", "zsh", "fish", "sh", "dash", "ksh", "csh", "tcsh",
5959
"pwsh", "powershell", "cmd.exe", "nu", "elvish", "xonsh",
60-
"login"
60+
"login",
61+
// Windows shell executables (returned with .exe suffix)
62+
"bash.exe", "pwsh.exe", "powershell.exe", "nu.exe",
63+
"fish.exe", "elvish.exe", "xonsh.exe", "wsl.exe"
6164
]);
6265

6366
/**

0 commit comments

Comments
 (0)