Connect enumeration window closes before a late slice-status burst, silently reproducing #4759

Open
#5,281 1 comment 0 reactions 0 assignees View on GitHub

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

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

bug GUI maintainer-review multi-pan protocol

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=1 on every connect.
  • The 3000 ms backstop does not help or hurt here; cancelArm() sets
    m_untilMs = 0 regardless.

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 by ensureDefaultSlicePreferringRestoredPan() 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from aethersdr/AetherSDR

All issues in aethersdr/AetherSDR

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.