]> sigrok.org Git - pulseview.git/commitdiff
Fix #805 by resetting selected device on failure
authorSoeren Apel <redacted>
Wed, 22 Jun 2016 16:02:34 +0000 (18:02 +0200)
committerUwe Hermann <redacted>
Fri, 24 Jun 2016 21:15:39 +0000 (23:15 +0200)
It can happen that devices can be selected but not used
(permissions problems, connection issues, driver issues, etc.),
so in those cases we want to fail gracefully instead of
segfaulting.
The reason for the segfault is the device selector button
isn't reset in case the device couldn't be opened, causing
the rest of the application to try and work with a device
instance that is actually invalid.

Resetting the device selector when the device failed to
open not only fixes this but also makes the UI more
consistent with the internal state.

pv/mainwindow.cpp
pv/session.cpp
pv/toolbars/mainbar.cpp
pv/toolbars/mainbar.hpp
pv/widgets/devicetoolbutton.cpp
pv/widgets/devicetoolbutton.hpp

index 4f6bc41d551c4182919539cb3810882f9e10e60d..2558cb07692fe497e87d262fad574bc81ad70bfd 100644 (file)
@@ -882,8 +882,11 @@ void MainWindow::device_selected()
 {
        // Set the title to include the device/file name
        const shared_ptr<devices::Device> device = session_.device();
 {
        // Set the title to include the device/file name
        const shared_ptr<devices::Device> device = session_.device();
-       if (!device)
+
+       if (!device) {
+               main_bar_->reset_device_selector();
                return;
                return;
+       }
 
        const string display_name = device->display_name(device_manager_);
        setWindowTitle(tr("%1 - PulseView").arg(display_name.c_str()));
 
        const string display_name = device->display_name(device_manager_);
        setWindowTitle(tr("%1 - PulseView").arg(display_name.c_str()));
index 73dd339b60fea95259d6fddc7aace7ec9f3ad0e1..b8e98ece9a5dce42ce5e6e774e689bd34abed5a0 100644 (file)
@@ -161,7 +161,15 @@ void Session::set_device(shared_ptr<devices::Device> device)
        signals_changed();
 
        device_ = std::move(device);
        signals_changed();
 
        device_ = std::move(device);
-       device_->open();
+
+       try {
+               device_->open();
+       } catch (const QString &e) {
+               device_.reset();
+               device_selected();
+               throw;
+       }
+
        device_->session()->add_datafeed_callback([=]
                (shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
                        data_feed_in(device, packet);
        device_->session()->add_datafeed_callback([=]
                (shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
                        data_feed_in(device, packet);
index 8c0b06391db310f8e1dad603cf38ad7de6c81864..cca4d9d5bab2d38cae0af4eb65de58718ef7d38f 100644 (file)
@@ -248,6 +248,11 @@ void MainBar::set_capture_state(pv::Session::capture_state state)
        sample_rate_.setEnabled(ui_enabled);
 }
 
        sample_rate_.setEnabled(ui_enabled);
 }
 
+void MainBar::reset_device_selector()
+{
+       device_selector_.reset();
+}
+
 void MainBar::update_sample_rate_selector()
 {
        Glib::VariantContainerBase gvar_dict;
 void MainBar::update_sample_rate_selector()
 {
        Glib::VariantContainerBase gvar_dict;
index 6e2a706833bc566c687e3d20a6bc7da51919de04..9c4b1cd4b0e4a9f9484d00736109b75a8f8cf8ee 100644 (file)
@@ -69,6 +69,8 @@ public:
 
        void set_capture_state(pv::Session::capture_state state);
 
 
        void set_capture_state(pv::Session::capture_state state);
 
+       void reset_device_selector();
+
 private:
        void update_sample_rate_selector();
        void update_sample_rate_selector_value();
 private:
        void update_sample_rate_selector();
        void update_sample_rate_selector_value();
index a0fc10e6f5a36de217cc2008cb1201e2f6bf0a02..d553aba32987d7bded07a7be5767d63501fb69c0 100644 (file)
@@ -73,11 +73,18 @@ void DeviceToolButton::set_device_list(
 {
        selected_device_ = selected;
        setText(selected ? QString::fromStdString(
 {
        selected_device_ = selected;
        setText(selected ? QString::fromStdString(
-               selected->display_name(device_manager_)) : "<No Device>");
+               selected->display_name(device_manager_)) : tr("<No Device>"));
        devices_ = vector< weak_ptr<Device> >(devices.begin(), devices.end());
        update_device_list();
 }
 
        devices_ = vector< weak_ptr<Device> >(devices.begin(), devices.end());
        update_device_list();
 }
 
+void DeviceToolButton::reset()
+{
+       setText(tr("<No Device>"));
+       selected_device_.reset();
+       update_device_list();
+}
+
 void DeviceToolButton::update_device_list()
 {
        menu_.clear();
 void DeviceToolButton::update_device_list()
 {
        menu_.clear();
@@ -108,6 +115,8 @@ void DeviceToolButton::on_action(QObject *action)
 {
        assert(action);
 
 {
        assert(action);
 
+       selected_device_.reset();
+
        Device *const dev = (Device*)((QAction*)action)->data().value<void*>();
        for (weak_ptr<Device> dev_weak_ptr : devices_) {
                shared_ptr<Device> dev_ptr(dev_weak_ptr);
        Device *const dev = (Device*)((QAction*)action)->data().value<void*>();
        for (weak_ptr<Device> dev_weak_ptr : devices_) {
                shared_ptr<Device> dev_ptr(dev_weak_ptr);
index ed69a4b64a4ef1b0209daf004f2192117a9af8c6..589fbf2338016138be21050dd250032d54a04050 100644 (file)
@@ -70,6 +70,12 @@ public:
                const std::list< std::shared_ptr<devices::Device> > &devices,
                std::shared_ptr<devices::Device> selected);
 
                const std::list< std::shared_ptr<devices::Device> > &devices,
                std::shared_ptr<devices::Device> selected);
 
+       /**
+        * Sets the current device to "no device". Useful for when a selected
+        * device fails to open.
+        */
+       void reset();
+
 private:
        /**
         * Repopulates the menu from the device list.
 private:
        /**
         * Repopulates the menu from the device list.