From c09beb1418e59013006746d8eb7919418c1ece5c Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Tue, 16 Apr 2019 17:20:23 +0800 Subject: [PATCH] Handle exceptions from SoapySDR during stream setup more cleanly. --- dump978_main.cc | 10 ++++++---- exception.h | 20 ++++++++++++++++++++ soapy_source.cc | 25 ++++++++++++++++++------- 3 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 exception.h diff --git a/dump978_main.cc b/dump978_main.cc index de75ac2..4cb8bd5 100644 --- a/dump978_main.cc +++ b/dump978_main.cc @@ -14,6 +14,7 @@ #include "convert.h" #include "demodulator.h" +#include "exception.h" #include "message_dispatch.h" #include "sample_source.h" #include "soapy_source.h" @@ -246,14 +247,15 @@ static int realmain(int argc, char **argv) { } int main(int argc, char **argv) { -#ifndef DEBUG_EXCEPTIONS try { return realmain(argc, argv); + } catch (const config_error &e) { + std::cerr << "Configuration error: " << e.what() << std::endl; + return 2; +#ifndef DEBUG_EXCEPTIONS } catch (...) { std::cerr << "Uncaught exception: " << boost::current_exception_diagnostic_information() << std::endl; return 2; - } -#else - return realmain(argc, argv); #endif + } } diff --git a/exception.h b/exception.h new file mode 100644 index 0000000..2dfc429 --- /dev/null +++ b/exception.h @@ -0,0 +1,20 @@ +// -*- c++ -*- + +// Copyright (c) 2019, FlightAware LLC. +// All rights reserved. +// Licensed under the 2-clause BSD license; see the LICENSE file + +#ifndef DUMP978_EXCEPTION_H +#define DUMP978_EXCEPTION_H + +#include + +namespace flightaware::uat { + class config_error : public std::runtime_error { + public: + explicit config_error(const std::string &what_arg) : runtime_error(what_arg) {} + explicit config_error(const char *what_arg) : runtime_error(what_arg) {} + }; +}; // namespace flightaware::uat + +#endif diff --git a/soapy_source.cc b/soapy_source.cc index 6c29dd3..47d9888 100644 --- a/soapy_source.cc +++ b/soapy_source.cc @@ -3,6 +3,7 @@ // Licensed under the 2-clause BSD license; see the LICENSE file #include "soapy_source.h" +#include "exception.h" #include #include @@ -100,9 +101,14 @@ SoapySampleSource::SoapySampleSource(boost::asio::io_service &service, const std SoapySampleSource::~SoapySampleSource() { Stop(); } void SoapySampleSource::Init() { - device_ = {SoapySDR::Device::make(device_name_), &SoapySDR::Device::unmake}; + try { + device_ = {SoapySDR::Device::make(device_name_), &SoapySDR::Device::unmake}; + } catch (const std::runtime_error &err) { + throw config_error(std::string("No matching SoapySDR device found (cause: ") + err.what() + ")"); + } + if (!device_) { - throw std::runtime_error("no suitable device found"); + throw config_error("No matching SoapySDR device found"); } // hacky mchackerson @@ -112,7 +118,7 @@ void SoapySampleSource::Init() { if (options_.count("sdr-auto-gain")) { if (!device_->hasGainMode(SOAPY_SDR_RX, 0)) { - throw std::runtime_error("device does not support automatic gain mode"); + throw config_error("Device does not support automatic gain mode"); } std::cerr << "SoapySDR: using automatic gain" << std::endl; device_->setGainMode(SOAPY_SDR_RX, 0, true); @@ -171,12 +177,12 @@ void SoapySampleSource::Init() { soapy_format = device_->getNativeStreamFormat(SOAPY_SDR_RX, 0, fullScale); format_ = SoapyToFormat(soapy_format); if (format_ == SampleFormat::UNKNOWN) { - throw std::runtime_error("Unsupported native SDR format: " + soapy_format + "; try specifying --format"); + throw config_error("Unsupported native SDR format: " + soapy_format + "; try specifying --format"); } } else { soapy_format = FormatToSoapy(format_); if (soapy_format.empty()) { - throw std::runtime_error("unsupported sample format"); + throw config_error("Unsupported sample format"); } } @@ -199,9 +205,14 @@ void SoapySampleSource::Init() { #endif } - stream_ = {device_->setupStream(SOAPY_SDR_RX, soapy_format, channels, stream_settings), std::bind(&SoapySDR::Device::closeStream, device_, std::placeholders::_1)}; + try { + stream_ = {device_->setupStream(SOAPY_SDR_RX, soapy_format, channels, stream_settings), std::bind(&SoapySDR::Device::closeStream, device_, std::placeholders::_1)}; + } catch (const std::runtime_error &err) { + throw config_error(std::string("Failed to construct soapysdr stream (cause: ") + err.what() + ")"); + } + if (!stream_) { - throw std::runtime_error("failed to construct stream"); + throw config_error("Failed to construct soapysdr stream"); } }