fix(operator-stream): recover the single-operator slot from a dead peer - #13
fix(operator-stream): recover the single-operator slot from a dead peer#13martinburian-ba wants to merge 1 commit into
Conversation
QuicOperatorServer::onConnected() unconditionally overwrote operatorConnection_, relying entirely on ba-quic-lib's maxConnections to keep out a second operator. That is fail-open when two handshakes reach CONNECTED simultaneously, and gave no path to reclaim the slot from a peer that vanished without a clean QUIC close (kill -9, crash, power loss) — a hard-killed GUI held streaming-control for the whole car until the ES process restarted. Port the fix already shipped in teleop-module's QuicOperatorServer: onConnected() now does an explicit check-and-set under operatorMutex_ and disconnects a second connection instead of silently replacing the tracked one. buildSettings() sets disconnectTimeoutMs explicitly to match ba-quic-lib's own default, mirroring the same precedent. BAF-1900
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| * the transport layer already (ConnectionShutdown), so — unlike the old hand-rolled version — this | ||
| * class no longer needs its own compare-and-swap "already have an operator" logic. | ||
| * | ||
| * BAF-1900 update: the above does not hold for two handshakes reaching CONNECTED simultaneously — |
There was a problem hiding this comment.
[CRITICAL] YouTrack ticket ID in comment: cpp-conventions forbids referencing YouTrack issues/task IDs in comments. This Doxygen doc comment leads with BAF-1900 update:. Describe the reasoning in plain language instead — the ticket ID belongs in the commit/PR, not the code.
| // against quic-lib's QuicServer.cpp) -- so onConnected() below is never called for a connection | ||
| // that loses the race, and this class no longer needs its own compare-and-swap "already have an | ||
| // operator" logic. | ||
| // BAF-1900 update: the above does not hold for two handshakes reaching CONNECTED simultaneously |
There was a problem hiding this comment.
[CRITICAL] YouTrack ticket ID in comment: Same issue — the constructor comment leads with BAF-1900 update:. Reword without the ticket ID.
| { | ||
| std::lock_guard<std::mutex> lock(operatorMutex_); | ||
| if (operatorConnection_ != id) { | ||
| // BAF-1900: also covers a connection rejected by onConnected()'s own disconnect() call. |
There was a problem hiding this comment.
[CRITICAL] YouTrack ticket ID in comment: Same issue — // BAF-1900: also covers a connection rejected.... Reword without the ticket ID.
|
[IMPORTANT] Does this fix the reported dead-peer lockout, or only a different race? BAF-1900's core symptom is a hard-killed GUI holding the operator slot for 30+ minutes while every new connection is rejected, and its suggested fix direction is "sane transport timeouts so a dead peer is detected, and/or newest-wins slot takeover." This PR appears to do neither:
If Was this validated against the ticket's actual repro ( Suggested BAF-1900 comment draft, if the deviation is intentional or the repro still fails (for the PR author to post, not something I'll post myself):
|
Summary
QuicOperatorServer::onConnected()unconditionally overwroteoperatorConnection_, relying entirely on ba-quic-lib'smaxConnectionsto keep out a second operator. That's fail-open when two handshakes reach CONNECTED simultaneously, and gave no way to reclaim the slot from a peer that vanished without a clean QUIC close (kill -9, crash, power loss) — a hard-killed GUI held streaming-control for the whole car until the ES process restarted.Fix
Ports the fix already shipped in teleop-module's
QuicOperatorServer(same class, same bug, fixed there first):onConnected()now does an explicit check-and-set underoperatorMutex_, logging a warning and callingquicServer_->disconnect(id)for a second connection instead of silently replacing the tracked one.buildSettings()setsdisconnectTimeoutMsexplicitly (matches ba-quic-lib's own default; set explicitly so the choice reads as deliberate, per the teleop-module precedent).Test plan
test/dir, no CTest/GTest wiring), so this wasn't covered by an automated test. Reviewed by hand against ba-quic-lib's vendored headers and against teleop-module's shipped fix for API/locking correctness.kill -9it → connect another GUI → commands should no longer be dropped.BAF-1900