Connect enumeration window closes before a late slice-status burst, silently reproducing #4759
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- cpp
- Domain
- desktop, networking
Research direction
Start in src/models/RadioModel.cpp around lines 6610-6625, then follow MainWindow::cancelArm(), onSliceAdded, and ConnectSliceEnumerationGuard. Trace the existing 500 ms deferred check and handleSliceStatus path. Done means the guard remains open only while slice statuses are still in flight, immediate-completion paths stay unchanged, and the cancellation/expiry state remains diagnosable.
Written by the indexing model from the issue text.
Description
Summary
ConnectSliceEnumerationGuard (merged in #4985, da6a2ebb) is disarmed when the
slice list reply arrives:
sendCmd("slice list",
[this](int code3, const QString& body) {
emit sliceConnectEnumerationFinished(); // -> MainWindow cancelArm()
src/models/RadioModel.cpp:6610
That is correct whenever the radio's slice-status burst precedes the slice list reply, which is what happens in practice — measured at 226–237 ms of
margin on a FLEX-8400 during the #4985 review, across eight live connects.
But the codebase already knows the ordering can invert. Immediately below, in
the same callback:
} else if (m_slices.isEmpty()) {
// Radio has slices but we haven't matched any to our
// client_handle yet (status messages still in flight).
// Defer the decision to give status messages time to
// arrive and populate m_slices via handleSliceStatus.
QTimer::singleShot(500, this, [this]() { ... });
src/models/RadioModel.cpp:6625
If that branch is taken, the window has already been closed by the emit a
few lines above. The slice statuses then arrive, MainWindow::onSliceAdded
runs with the guard shut, firstSliceSelectionSource(false) returns
TopologyFallback, and slice set <n> active=1 goes on the wire — which is
#4759.
Why it is low severity
- It degrades to the behaviour that shipped before #4985, so nothing
regresses relative to any released build. - It is strictly narrower than the pre-#4985 behaviour, which asserted
active=1on every connect. - The 3000 ms backstop does not help or hurt here;
cancelArm()sets
m_untilMs = 0regardless.
Why it is worth closing anyway
The failure is silent. ConnectSliceEnumerationGuard::expiredUnused() — the
diagnostic added for exactly this class of problem — cannot fire, because it
requires m_untilMs > 0 and cancelArm() has zeroed it:
bool expiredUnused(qint64 nowMs) const
{
return m_untilMs > 0 && nowMs >= m_untilMs && !m_consulted;
}
So an operator hitting this sees their active slice revert with no log line and
no visible difference from a normal launch — the same reporting problem that let
#4759 sit unexplained.
Suggested shape
Defer the sliceConnectEnumerationFinished() emit in exactly the branch that
knows statuses are still in flight, rather than emitting unconditionally at the
top of the callback:
ids.isEmpty()→ emit immediately (enumeration really is over; the default
slice created byensureDefaultSlicePreferringRestoredPan()should take
TopologyFallback, which is what happens today and is correct).!ids.isEmpty() && m_slices.isEmpty()→ hold the window open, and emit
from the existing 500 ms deferred check instead.- otherwise → emit immediately.
Separately, expiredUnused() conflates "armed then expired" with "never armed
at decision time" and now also with "explicitly cancelled". Distinguishing them
would make this diagnosable if it ever does happen in the field.
Provenance
Found during the #4985 review; deliberately not blocked on, since #4985 is a
strict improvement over main on every path. Ordering margins above are from
live FLEX-8400 captures (firmware 4.2.20.41343), not inference — see the review
thread on #4985 for the timestamped runs.
👨🏼💻 Co-authored by Claude Opus 5
- Dominant language
- C++
- Stars
- 221
- Forks
- 117
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 299
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aethersdr/AetherSDR
-
audio documentation good first issue maintainer-review
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
bug CW maintainer-review safety
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
docs(agents): family PRs must stay in the family tree (shared applet/pan/model edits stall review) Opendocumentation enhancement maintainer-review
Difficulty 1/5 1-3 hours Newbie friendliness 90/100
-
bug good first issue GUI maintainer-review priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 86/100
All issues in aethersdr/AetherSDR
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
Sensor initialization takes very long when `--initial-sim-time` is set to current UNIX timestamp Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
gazebosim/gz-sensors#662 · 1 comment ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
LadybirdBrowser/ladybird#12123 ·