]> sigrok.org Git - pulseview.git/blobdiff - pv/data/decodesignal.cpp
Fix #1596 by fixing some race conditions
[pulseview.git] / pv / data / decodesignal.cpp
index 256c29b8c9f34d65d090ab8a77ca1e4d563d32f3..b9a1fabc74917fc2cc8791ed9ae7abe8ff04b38b 100644 (file)
@@ -56,8 +56,7 @@ DecodeSignal::DecodeSignal(pv::Session &session) :
        srd_session_(nullptr),
        logic_mux_data_invalid_(false),
        stack_config_changed_(true),
-       current_segment_id_(0),
-       error_message_("")
+       current_segment_id_(0)
 {
        connect(&session_, SIGNAL(capture_state_changed(int)),
                this, SLOT(on_capture_state_changed(int)));
@@ -171,7 +170,7 @@ void DecodeSignal::reset_decode(bool shutting_down)
        logic_mux_data_invalid_ = true;
 
        if (!error_message_.isEmpty()) {
-               error_message_ = QString();
+               error_message_.clear();
                // TODO Emulate noquote()
                qDebug().nospace() << name() << ": Error cleared";
        }
@@ -266,12 +265,6 @@ bool DecodeSignal::is_paused() const
        return decode_paused_;
 }
 
-QString DecodeSignal::error_message() const
-{
-       lock_guard<mutex> lock(output_mutex_);
-       return error_message_;
-}
-
 const vector<decode::DecodeChannel> DecodeSignal::get_channels() const
 {
        return channels_;
@@ -316,7 +309,7 @@ void DecodeSignal::auto_assign_signals(const shared_ptr<Decoder> dec)
                }
 
                if (match) {
-                       ch.assigned_signal = match.get();
+                       ch.assigned_signal = match;
                        new_assignment = true;
                }
        }
@@ -329,7 +322,7 @@ void DecodeSignal::auto_assign_signals(const shared_ptr<Decoder> dec)
        }
 }
 
-void DecodeSignal::assign_signal(const uint16_t channel_id, const SignalBase *signal)
+void DecodeSignal::assign_signal(const uint16_t channel_id, shared_ptr<const SignalBase> signal)
 {
        for (decode::DecodeChannel& ch : channels_)
                if (ch.id == channel_id) {
@@ -347,7 +340,7 @@ int DecodeSignal::get_assigned_signal_count() const
 {
        // Count all channels that have a signal assigned to them
        return count_if(channels_.begin(), channels_.end(),
-               [](decode::DecodeChannel ch) { return ch.assigned_signal; });
+               [](decode::DecodeChannel ch) { return ch.assigned_signal.get(); });
 }
 
 void DecodeSignal::set_initial_pin_state(const uint16_t channel_id, const int init_state)
@@ -406,8 +399,9 @@ int64_t DecodeSignal::get_working_sample_count(uint32_t segment_id) const
                        if (segment_id >= logic_data->logic_segments().size())
                                return 0;
 
-                       const shared_ptr<LogicSegment> segment = logic_data->logic_segments()[segment_id];
-                       count = min(count, (int64_t)segment->get_sample_count());
+                       const shared_ptr<const LogicSegment> segment = logic_data->logic_segments()[segment_id]->get_shared_ptr();
+                       if (segment)
+                               count = min(count, (int64_t)segment->get_sample_count());
                }
 
        return (no_signals_assigned ? 0 : count);
@@ -814,7 +808,7 @@ void DecodeSignal::restore_settings(QSettings &settings)
 
                for (const shared_ptr<data::SignalBase>& signal : signalbases)
                        if ((signal->name() == assigned_signal_name) && (signal->type() != SignalBase::DecodeChannel))
-                               channel->assigned_signal = signal.get();
+                               channel->assigned_signal = signal;
 
                channel->initial_pin_state = settings.value("initial_pin_state").toInt();
 
@@ -829,13 +823,6 @@ void DecodeSignal::restore_settings(QSettings &settings)
        begin_decode();
 }
 
-void DecodeSignal::set_error_message(QString msg)
-{
-       error_message_ = msg;
-       // TODO Emulate noquote()
-       qDebug().nospace() << name() << ": " << msg;
-}
-
 bool DecodeSignal::all_input_segments_complete(uint32_t segment_id) const
 {
        bool all_complete = true;
@@ -852,8 +839,8 @@ bool DecodeSignal::all_input_segments_complete(uint32_t segment_id) const
                        if (segment_id >= logic_data->logic_segments().size())
                                return false;
 
-                       const shared_ptr<LogicSegment> segment = logic_data->logic_segments()[segment_id];
-                       if (!segment->is_complete())
+                       const shared_ptr<const LogicSegment> segment = logic_data->logic_segments()[segment_id]->get_shared_ptr();
+                       if (segment && !segment->is_complete())
                                all_complete = false;
                }
 
@@ -892,8 +879,10 @@ double DecodeSignal::get_input_samplerate(uint32_t segment_id) const
                                continue;
 
                        try {
-                               const shared_ptr<LogicSegment> segment = logic_data->logic_segments().at(segment_id);
-                               samplerate = segment->samplerate();
+                               const shared_ptr<const LogicSegment> segment =
+                                       logic_data->logic_segments().at(segment_id)->get_shared_ptr();
+                               if (segment)
+                                       samplerate = segment->samplerate();
                        } catch (out_of_range&) {
                                // Do nothing
                        }
@@ -1020,7 +1009,7 @@ void DecodeSignal::mux_logic_samples(uint32_t segment_id, const int64_t start, c
                return;
 
        // Fetch the channel segments and their data
-       vector<shared_ptr<LogicSegment> > segments;
+       vector<shared_ptr<const LogicSegment> > segments;
        vector<const uint8_t*> signal_data;
        vector<uint8_t> signal_in_bytepos;
        vector<uint8_t> signal_in_bitpos;
@@ -1029,14 +1018,19 @@ void DecodeSignal::mux_logic_samples(uint32_t segment_id, const int64_t start, c
                if (ch.assigned_signal) {
                        const shared_ptr<Logic> logic_data = ch.assigned_signal->logic_data();
 
-                       shared_ptr<LogicSegment> segment;
-                       try {
-                               segment = logic_data->logic_segments().at(segment_id);
-                       } catch (out_of_range&) {
+                       shared_ptr<const LogicSegment> segment;
+                       if (segment_id < logic_data->logic_segments().size()) {
+                               segment = logic_data->logic_segments().at(segment_id)->get_shared_ptr();
+                       } else {
                                qDebug() << "Muxer error for" << name() << ":" << ch.assigned_signal->name() \
                                        << "has no logic segment" << segment_id;
+                               logic_mux_interrupt_ = true;
                                return;
                        }
+
+                       if (!segment)
+                               return;
+
                        segments.push_back(segment);
 
                        uint8_t* data = new uint8_t[(end - start) * segment->unit_size()];
@@ -1048,7 +1042,6 @@ void DecodeSignal::mux_logic_samples(uint32_t segment_id, const int64_t start, c
                        signal_in_bitpos.push_back(bitpos % 8);
                }
 
-
        shared_ptr<LogicSegment> output_segment;
        try {
                output_segment = logic_mux_data_->logic_segments().at(segment_id);
@@ -1056,6 +1049,7 @@ void DecodeSignal::mux_logic_samples(uint32_t segment_id, const int64_t start, c
                qDebug() << "Muxer error for" << name() << ": no logic mux segment" \
                        << segment_id << "in mux_logic_samples(), mux segments size is" \
                        << logic_mux_data_->logic_segments().size();
+               logic_mux_interrupt_ = true;
                return;
        }
 
@@ -1118,8 +1112,7 @@ void DecodeSignal::logic_mux_proc()
 
        // Create initial logic mux segment
        shared_ptr<LogicSegment> output_segment =
-               make_shared<LogicSegment>(*logic_mux_data_, segment_id,
-                       logic_mux_unit_size_, 0);
+               make_shared<LogicSegment>(*logic_mux_data_, segment_id, logic_mux_unit_size_, 0);
        logic_mux_data_->push_segment(output_segment);
 
        output_segment->set_samplerate(get_input_samplerate(0));
@@ -1186,7 +1179,7 @@ void DecodeSignal::logic_mux_proc()
 
 void DecodeSignal::decode_data(
        const int64_t abs_start_samplenum, const int64_t sample_count,
-       const shared_ptr<LogicSegment> input_segment)
+       const shared_ptr<const LogicSegment> input_segment)
 {
        const int64_t unit_size = input_segment->unit_size();
        const int64_t chunk_sample_count = DecodeChunkLength / unit_size;
@@ -1250,8 +1243,9 @@ void DecodeSignal::decode_proc()
        if (decode_interrupt_)
                return;
 
-       shared_ptr<LogicSegment> input_segment = logic_mux_data_->logic_segments().front();
-       assert(input_segment);
+       shared_ptr<const LogicSegment> input_segment = logic_mux_data_->logic_segments().front()->get_shared_ptr();
+       if (!input_segment)
+               return;
 
        // Create the initial segment and set its sample rate so that we can pass it to SRD
        create_decode_segment();
@@ -1302,7 +1296,8 @@ void DecodeSignal::decode_proc()
                                        terminate_srd_session();
                                } else {
                                        // All segments have been processed
-                                       decode_finished();
+                                       if (!decode_interrupt_)
+                                               decode_finished();
                                }
                        } else {
                                // Wait for more input data
@@ -1311,11 +1306,6 @@ void DecodeSignal::decode_proc()
                        }
                }
        } while (!decode_interrupt_);
-
-       // Potentially reap decoders when the application no longer is
-       // interested in their (pending) results.
-       if (decode_interrupt_)
-               terminate_srd_session();
 }
 
 void DecodeSignal::start_srd_session()
@@ -1432,7 +1422,7 @@ void DecodeSignal::connect_input_notifiers()
                if (!ch.assigned_signal)
                        continue;
 
-               const data::SignalBase *signal = ch.assigned_signal;
+               const data::SignalBase *signal = ch.assigned_signal.get();
                connect(signal, &data::SignalBase::samples_cleared,
                        this, &DecodeSignal::on_data_cleared);
                connect(signal, &data::SignalBase::samples_added,