diff --git a/frontend/src/process-manager.ts b/frontend/src/process-manager.ts index 6f44d5d..0370863 100644 --- a/frontend/src/process-manager.ts +++ b/frontend/src/process-manager.ts @@ -205,9 +205,10 @@ export class ProcessManager { if (killButton) { const pid = Number.parseInt(killButton.dataset.processKillPid ?? '', 10); if (!Number.isSafeInteger(pid) || pid <= 0) return; - const row = killButton.closest('tr'); - const commandCell = row?.children.item(7); - const command = commandCell?.textContent ?? '--'; + // Reuse the command text already stored on the button's title attribute (set in render()). + // Avoids depending on the table's column order via children.item(N), which breaks when + // columns are added or rearranged. + const command = killButton.title || '--'; this.openKillDialog(pid, command); return; } @@ -630,8 +631,8 @@ export class ProcessManager { const fragment = document.createDocumentFragment(); const language = this.getLanguage(); - const killLabelZh = '强制结束'; - const killLabelEn = 'Force terminate'; + const killLabelZh = '结束进程'; + const killLabelEn = 'Terminate process'; for (const process of this.sortedProcesses(snapshot.processes)) { const row = document.createElement('tr'); const values = [ diff --git a/src/backend/session.ts b/src/backend/session.ts index 61a7ac0..8aa2bb6 100644 --- a/src/backend/session.ts +++ b/src/backend/session.ts @@ -1138,6 +1138,15 @@ export class SSHSession { stdout: '', stderr: 'Timed out opening the kill channel', }); + // Release the pending kill entry (with its decoders + stdout/stderr buffers) + // so repeated timeouts cannot accumulate in worker memory. We deliberately + // do NOT delete from this.channels here — keeping the SSH channel registered + // means a late CHANNEL_OPEN_CONFIRMATION still resolves in handleChannel() + // (channel found in this.channels) and falls through to the generic close + // branch instead of throwing "unknown recipient". The resulting + // CHANNEL_CLOSE handler then finds no pending kill and quietly skips + // finalize, so there is no double result-send. + this.pendingProcessKillChannels.delete(expected.channelID); if (expected.channel.isOpen()) void this.sendAuxiliaryChannelClose(expected.channel); }