Found during the v0.1.0 end-to-end test on a freshly installed host. View works; clicking to control always disconnects. Reproduced 4/4 times.
What happens
The host accepts everything correctly, then the entire QUIC session dies 8ms later.
Host (sigil 0.1.0, fresh install from the published release):
22:00:27.111 slot-0 focus state changed action=Request transition_reason=Requested
22:00:27.126 input v2 client accepted session_id=2 focus_generation=2 authorization_revision=2
22:00:27.134 shared-generation media feedback contributor released
22:00:27.134 input v2 client released
22:00:27.134 input v2 connection ended error=I/O error: connection lost
22:00:27.134 probe stream error err=transport: session error
22:00:27.134 subscribed cancelled video/h264 + audio/opus
22:00:27.134 multi-viewer session membership changed active_viewers=0 reason="disconnected"
Portal (0.1.0, macOS arm64, run from a terminal to capture stderr):
[client] moq catalog: goq-v2-authenticated <- view working
[client] adaptive decision read failed: I/O error: connection lost
[client] invalid control v2 message: I/O error: connection lost
[moq_net::lite::subscriber] subscribe error id=1 audio/opus err=transport: session error
[moq_net::lite::subscriber] subscribe error id=2 video/h264 err=transport: session error
[client] timed out waiting for endpoint shutdown after explicit connection close
[iroh::socket][ERROR] Endpoint dropped without calling `Endpoint::close`. Aborting ungracefully.
Why this is an endpoint bug, not a session bug
- The host accepts the input v2 client. This is not a rejection or an authorization failure.
- Portal does not crash; the process survives.
- Control v2, media, audio, and media-feedback all report
connection lost simultaneously. Those are separate connections, so the common factor is the iroh Endpoint itself.
Endpoint dropped without calling Endpoint::close fires when the last reference goes away.
The subsequent timed out waiting for endpoint shutdown after explicit connection close (media/connect.rs:574) is the aftermath — disconnect_client runs against an endpoint that is already gone, which is why it times out.
Hypothesis
start_focused_input_v2 (media/input_delivery.rs:512) takes context.endpoint from state.v2_input_context. Entering control also advances the roster/snapshot. If that path clears or replaces v2_input_context while its Endpoint clone is the last strong reference, dropping the context drops the endpoint, which kills every connection at once. That matches the timing and the "all at once" signature exactly.
Worth checking whether anything other than state.client_endpoint is expected to keep the endpoint alive.
Environment
- Host: Bazzite 43 Kinoite, installed via
curl -fsSL https://goq.sh/install-sigil | bash, activation guide followed end to end
- Capture: gamescope-pipewire, 2560x1600@60,
vah264enc on /dev/dri/renderD128, external-gst-launch backend
- Portal: v0.1.0 macOS arm64 from the published release
- Enrollment: fresh, grants
view,pointer-keyboard,gamepad
- Host preflight was clean: capture probe 300 frames, 0 post-encode drops, 58.2 fps
Found during the v0.1.0 end-to-end test on a freshly installed host. View works; clicking to control always disconnects. Reproduced 4/4 times.
What happens
The host accepts everything correctly, then the entire QUIC session dies 8ms later.
Host (
sigil 0.1.0, fresh install from the published release):Portal (0.1.0, macOS arm64, run from a terminal to capture stderr):
Why this is an endpoint bug, not a session bug
connection lostsimultaneously. Those are separate connections, so the common factor is the irohEndpointitself.Endpoint dropped without calling Endpoint::closefires when the last reference goes away.The subsequent
timed out waiting for endpoint shutdown after explicit connection close(media/connect.rs:574) is the aftermath —disconnect_clientruns against an endpoint that is already gone, which is why it times out.Hypothesis
start_focused_input_v2(media/input_delivery.rs:512) takescontext.endpointfromstate.v2_input_context. Entering control also advances the roster/snapshot. If that path clears or replacesv2_input_contextwhile itsEndpointclone is the last strong reference, dropping the context drops the endpoint, which kills every connection at once. That matches the timing and the "all at once" signature exactly.Worth checking whether anything other than
state.client_endpointis expected to keep the endpoint alive.Environment
curl -fsSL https://goq.sh/install-sigil | bash, activation guide followed end to endvah264encon/dev/dri/renderD128, external-gst-launch backendview,pointer-keyboard,gamepad