From eabab30571539818bc8e9cb8c853be8d5d0fdab2 Mon Sep 17 00:00:00 2001 From: Hako Date: Thu, 1 Oct 2026 16:58:03 +0900 Subject: [PATCH 1/2] fix(server): drop typing and keys whose connection closed while they waited behind a message --- CHANGELOG.md | 6 ++++++ server/index.ts | 4 ++++ server/submit.contract.test.ts | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e77ecdb217..7f61a9a4c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ between releases do not reach them. Remote-PC runtime bundles are versioned sepa ## [Unreleased] +### Fixed +- A Stop, an Enter or anything typed right after a message no longer reaches the pane once the + connection that sent it has closed. It waited behind the message and was sent afterwards, with + nobody watching. The message itself is still finished for a phone that locks + (PRLINK). + ## [0.3.38] - 2026-10-01 ### Added diff --git a/server/index.ts b/server/index.ts index e1de710e9b..d3ac96b7d4 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1387,6 +1387,8 @@ export function createServer( void serialize(message.pane_id, () => { // held while this waited its turn: it goes nowhere, as unqueued typing would if (attachments.get(message.pane_id)?.held) return; + // nothing typed outlives its connection + if (!clients.has(client)) return; authorizeSocket(client); return paneSendText(message.pane_id, text); }).catch(() => undefined); @@ -1427,6 +1429,8 @@ export function createServer( send(client, { type: "error", code: "attach_held", message: ATTACH_HELD_MESSAGE, pane_id: message.pane_id }); return; } + // a key pressed by a connection that has gone since is not pressed + if (!clients.has(client)) return; authorizeSocket(client); return paneSendKeys(message.pane_id, message.keys); }); diff --git a/server/submit.contract.test.ts b/server/submit.contract.test.ts index c6a894a4c8..b5e7b3ae79 100644 --- a/server/submit.contract.test.ts +++ b/server/submit.contract.test.ts @@ -298,6 +298,29 @@ describe("WebSocket submit", () => { expect(typed(shell, from)).toBe("gone\r"); }, 30_000); + it("sends nothing typed or keyed by a connection that closed while it waited behind a message", async () => { + const gone = await Socket.connect(); + const socket = await Socket.connect(); + try { + gone.send({ type: "attach", pane_id: shell.pane, cols: 100, rows: 30 }); + await gone.waitFor((message) => message.type === "pty-data" && message.pane_id === shell.pane); + const from = chunks(shell).length; + // the message is finished for a sender that left; the Stop and the Enter behind it are not + gone.send({ type: "submit", id: 30, pane_id: shell.pane, text: "one", payload: "one" }); + gone.send({ type: "input", pane_id: shell.pane, text: "\u001b" }); + gone.send({ type: "keys", pane_id: shell.pane, keys: ["Enter"] }); + gone.close(); + await received(shell, from, 1); + socket.send({ type: "submit", id: 31, pane_id: shell.pane, text: "two", payload: "two" }); + await socket.result(31); + await received(shell, from, 2); + expect(typed(shell, from)).toBe("one\rtwo\r"); + } finally { + gone.close(); + socket.close(); + } + }, 30_000); + it("answers a submit from an observe connection with read_only, typing nothing", async () => { const socket = await Socket.connect(); try { From 4409103f26f62dc3355742c85eadef4162f302f3 Mon Sep 17 00:00:00 2001 From: Hako Date: Thu, 1 Oct 2026 16:58:08 +0900 Subject: [PATCH 2/2] docs(changelog): link #235 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f61a9a4c1..9ccdcbd231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ between releases do not reach them. Remote-PC runtime bundles are versioned sepa - A Stop, an Enter or anything typed right after a message no longer reaches the pane once the connection that sent it has closed. It waited behind the message and was sent afterwards, with nobody watching. The message itself is still finished for a phone that locks - (PRLINK). + ([#235](https://github.com/devswha/herdr-web-ui/pull/235)). ## [0.3.38] - 2026-10-01