fix: use Get-NetTCPConnection for locale-independent port lookup
The netstat-based parser matched the literal English "LISTENING" state string, which is translated on non-English Windows (e.g. "ABHÖREN", "ÉCOUTE", "ESCUTANDO"). On those systems the regex matched zero lines, so killProcessOnPort silently did nothing -- fail-open, not a regression, but ineffective for the exact users the fix targets. Replace it with `Get-NetTCPConnection -State Listen -LocalPort <port>`, which reads the same underlying WinNT API netstat's display layer translates, so it's unaffected by OS display language. Verified against a real listening port on this machine (matched the actual owning PID). Also fixed a stale duplicate of the "killProcessOnPort is a no-op on Windows" comment left behind in server/index.js.
This commit is contained in:
@@ -627,21 +627,12 @@ describe('killProcessOnPort on Windows', () => {
|
||||
Object.defineProperty(process, 'platform', { value: platform, configurable: true });
|
||||
};
|
||||
|
||||
const netstatOutput = (port, pid) => [
|
||||
'',
|
||||
'Active Connections',
|
||||
'',
|
||||
' Proto Local Address Foreign Address State PID',
|
||||
` TCP 0.0.0.0:${port} 0.0.0.0:0 LISTENING ${pid}`,
|
||||
'',
|
||||
].join('\r\n');
|
||||
|
||||
it('force-kills the process listening on the target port via taskkill', () => {
|
||||
setPlatform('win32');
|
||||
const orphanPid = 54321;
|
||||
spawnSyncMock.mockImplementation((cmd) => {
|
||||
if (cmd === 'netstat') {
|
||||
return { stdout: netstatOutput(45678, orphanPid) };
|
||||
if (cmd === 'powershell') {
|
||||
return { stdout: `${orphanPid}\r\n` };
|
||||
}
|
||||
return { stdout: '' };
|
||||
});
|
||||
@@ -649,7 +640,11 @@ describe('killProcessOnPort on Windows', () => {
|
||||
const runtime = createRuntime();
|
||||
runtime.killProcessOnPort(45678);
|
||||
|
||||
expect(spawnSyncMock).toHaveBeenCalledWith('netstat', ['-ano'], expect.objectContaining({ windowsHide: true }));
|
||||
expect(spawnSyncMock).toHaveBeenCalledWith(
|
||||
'powershell',
|
||||
expect.arrayContaining([expect.stringContaining('-LocalPort 45678')]),
|
||||
expect.objectContaining({ windowsHide: true })
|
||||
);
|
||||
expect(spawnSyncMock).toHaveBeenCalledWith(
|
||||
'taskkill',
|
||||
['/PID', String(orphanPid), '/F'],
|
||||
@@ -660,8 +655,8 @@ describe('killProcessOnPort on Windows', () => {
|
||||
it('never force-kills its own process id', () => {
|
||||
setPlatform('win32');
|
||||
spawnSyncMock.mockImplementation((cmd) => {
|
||||
if (cmd === 'netstat') {
|
||||
return { stdout: netstatOutput(45678, process.pid) };
|
||||
if (cmd === 'powershell') {
|
||||
return { stdout: `${process.pid}\r\n` };
|
||||
}
|
||||
return { stdout: '' };
|
||||
});
|
||||
@@ -675,8 +670,8 @@ describe('killProcessOnPort on Windows', () => {
|
||||
it('does nothing when no process is listening on the target port', () => {
|
||||
setPlatform('win32');
|
||||
spawnSyncMock.mockImplementation((cmd) => {
|
||||
if (cmd === 'netstat') {
|
||||
return { stdout: netstatOutput(9999, 54321) };
|
||||
if (cmd === 'powershell') {
|
||||
return { stdout: '' };
|
||||
}
|
||||
return { stdout: '' };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user