Skip to content

Fix crash on device start when the driver reports sample rates as a range - #1054

Merged
cjcliffe merged 1 commit into
cjcliffe:masterfrom
aliaga17:fix/samplerate-zero-crash
Sep 2, 2026
Merged

cjcliffe merged 1 commit into
cjcliffe:masterfrom
aliaga17:fix/samplerate-zero-crash

Conversation

@aliaga17

Copy link
Copy Markdown
Contributor

Problem

Selecting a device whose SoapySDR driver only implements getSampleRateRange() (no discrete listSampleRates()) aborts CubicSDR on start:

[INFO] SoapyUSDR::setSampleRate(0, RX, 0 MHz)
[INFO] SoapyUSDR::setSampleRate(0, RX, 0 MHz) - error -22
libc++abi: terminating due to uncaught exception of type std::runtime_error:
SoapyUSDR::setSampleRate() unable to set samplerate!

Observed with the Wavelet Lab xSDR (usdr Soapy module, reports a continuous 1-125 MSps range), but any range-only driver is affected.

Root cause

Two issues in SDRDeviceInfo::getSampleRates():

  1. For range-only drivers, SoapySDR's deprecated-API shim expands the range into a stepped list whose first entry is 0.0. The 0 survives CubicSDR's decimation step, getSampleRateNear() selects it (it wins ties against valid rates), and the driver throws on setSampleRate(0). The exception is never caught, so the app aborts.
  2. If a driver returns an empty rate list, the existing code calls sampleRates.back() on an empty vector, which is undefined behavior.

Fix

  • Filter non-positive rates out of the listSampleRates() result.
  • If the list is empty, synthesize candidates from getSampleRateRange() (common rates that fall within the reported ranges, falling back to the range endpoints).
  • Return an empty list cleanly if the driver provides no rate information at all, instead of reading past the end of an empty vector.

Existing discrete-list drivers are unaffected: their lists contain no non-positive entries and are non-empty, so both new paths are no-ops.

Testing

Verified on a Wavelet Lab xSDR over USB on macOS (arm64, SoapySDR 0.8.1): device selection previously aborted the app 100% of the time; with this change it starts, streams, and the sample-rate menu is populated with valid rates.

🤖 Generated with Claude Code

Drivers that only implement getSampleRateRange() (e.g. the usdr module
for Wavelet Lab xSDR) crash CubicSDR on device start with:

  terminating due to uncaught exception of type std::runtime_error:
  SoapyUSDR::setSampleRate() unable to set samplerate!

Two problems in SDRDeviceInfo::getSampleRates():

- SoapySDR's deprecated-API shim expands a continuous rate range into
  a stepped list whose first entry is 0. The 0 survives decimation,
  getSampleRateNear() picks it, and the driver throws on
  setSampleRate(0). Filter out non-positive rates.
- If a driver returns an empty rate list, the existing code calls
  sampleRates.back() on an empty vector (undefined behavior).
  Synthesize a candidate list from getSampleRateRange() instead, fall
  back to the range endpoints, and bail out cleanly if there is no
  rate information at all.

Verified on a Wavelet Lab xSDR over USB: device selection previously
aborted the app, now starts and streams normally.
@cjcliffe

cjcliffe commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Seems like a reasonable solution when the list is empty/zero/range-only; checks passed on pr test branch -- thanks

@cjcliffe
cjcliffe merged commit 15b967f into cjcliffe:master Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants