Open martinpitt opened 8 hours ago
I tried to force ensure_transport()
early on, to avoid sending that init
message in the middle of the page. With that change (in addition to the fsinfo call) I get a much stronger failure:
--- pkg/systemd/terminal.jsx
+++ pkg/systemd/terminal.jsx
@@ -7,17 +7,16 @@ import { createRoot } from "react-dom/client";
import { FormSelect, FormSelectOption } from "@patternfly/react-core/dist/esm/components/FormSelect/index.js";
import { NumberInput } from "@patternfly/react-core/dist/esm/components/NumberInput/index.js";
import { Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from "@patternfly/react-core/dist/esm/components/Toolbar/index.js
";
-import { Alert, AlertActionCloseButton, AlertActionLink } from "@patternfly/react-core/dist/esm/components/Alert/index.js";
+import { ensure_transport } from 'cockpit/_internal/transport';
import { fsinfo } from "cockpit/fsinfo";
-
import "./terminal.scss";
import { Terminal } from "cockpit-components-terminal.jsx";
const _ = cockpit.gettext;
-(function() {
+ensure_transport(() => {
cockpit.translate();
/*
@@ -293,4 +299,4 @@ const _ = cockpit.gettext;
/* And show the body */
document.body.removeAttribute("hidden");
-}());
+});
That immediately kills the session with cockpit-ws saying
cockpit-ws[1278]: cannot open a channel 4:2!1 with the same id as another channel
I originally tried this with wrapping the terminal.jsx page into cockpit.transport.wait()
, but that doesn't suffice.
So indeed the terminal.jsx now sends two init messages. The first one through I don't know where from (most probably not from peer.py, but I see nothing else), and the second one from pkg/lib/cockpit/_internal/transport.ts #ws.onopen()
, where I added an extra NN: 1
field:
XXX shell router: got init
Object { command: "init", version: 1 }
for child
Window https://127.0.0.2:9091/cockpit/@localhost/system/terminal.html#/
not having source yet [shell.js:43258:21](https://127.0.0.2:9091/cockpit/@localhost/shell/shell.js)
XXX shell router: got init
Object { command: "init", NN: 1, version: 1 }
for child
Window https://127.0.0.2:9091/cockpit/@localhost/system/terminal.html#/
unregistering source
Object { name: "cockpit1:localhost/system/terminal", window: Window, channel_seed: "1:1!", default_host: "localhost", page: "system/terminal", inited: true }
So it feels like mixing old-style and new-style Channel
s really doesn't work. But I thought even the "old-style" channels from cockpit.js used cockpit/_internal/transport.ts..
AAAAARGH! I get it now. It's because of pkg/lib/cockpit/_internal/transport.ts TransportGlobals
, which are not really a singleton when "linking" it both into the bundle (as it happens with new-style channels) but also <script>
ing cockpit.js
from pages -- which we do everywhere in cockpit except kdump, and we also bundle it in cockpit-files. That's why the latter works just fine.
Fixed in #21059
Broken out from https://github.com/cockpit-project/cockpit/pull/21162
In that PR we try to add an fsinfo.ts
fsinfo()
call into the Terminal page, which completely breaks the existing bash spawn channel (and others). This page also uses a classiccockpit.channel()
. Incidentally this is similar to #21059 where trying to port the sosreport page tofsinfo()
also wreaks havoc -- that also uses a cockpit.channel().When changing the URL path on the terminal page, this happens, which explains the disconnect:
This is done by pkg/shell/router.jsx's
unregister()
:This happens in response to an
init
message that the terminal apparently sends ... to itself!?Debugging on the bridge side confirms that the kill() is really the first thing, i.e. it's not a weird fallout from fsinfo. And yet, when I replace the fsinfo call with a
throw new Error("XXX fake failure")
(or with a more complicated delayed sleep rejection) I don't get the kill.This is easier (less interactive) to investigate like this:
My first suspicion was colliding channel IDs (due to the occasional "with the same id as another channel" ws crash), but at first sight that doesn't seem to be the case.
One bug in the "new" transport is that the fsinfo channel immediately fails with "received message before init: ready", or sometimes with "ping". pkg/lib/cockpit/fsinfo.ts doesn't directly send "ping" or "ready", so whatever does that needs to wait for the transport to be ready.
It works reliably when opening the frame directly, without the shell: https://127.0.0.2:9091/cockpit/@localhost/system/terminal.html . This corroborates interference from the shell/routing.
I also replaced the
fsinfo.ts
fsinfo()
call (which uses the "new-style" channels) with the classic:and that works fine -- so it's really not a bridge problem, but mixing old- and new-style Transport/Channel with our shell Router.
Originally posted by @martinpitt in https://github.com/cockpit-project/cockpit/issues/21162#issuecomment-2456566895