From 887d270a8327da46a89d8e5375f172db778f0ff9 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sat, 25 Mar 2017 18:21:12 +0100 Subject: Fix race condition for PipelinedModCodec thread startup The thread could start before the vtable containing the subclass function is ready, leading to a crash because the thread calls a pure virtual function. --- src/FIRFilter.cpp | 2 ++ src/FIRFilter.h | 2 +- src/GainControl.cpp | 2 ++ src/ModPlugin.cpp | 10 ++++++++-- src/ModPlugin.h | 9 +++++++-- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp index 0e85e0f..4296822 100644 --- a/src/FIRFilter.cpp +++ b/src/FIRFilter.cpp @@ -83,6 +83,8 @@ FIRFilter::FIRFilter(const std::string& taps_file) : RC_ADD_PARAMETER(tapsfile, "Filename containing filter taps. When written to, the new file gets automatically loaded."); load_filter_taps(m_taps_file); + + start_pipeline_thread(); } void FIRFilter::load_filter_taps(const std::string &tapsFile) diff --git a/src/FIRFilter.h b/src/FIRFilter.h index 1fe0004..fb6b4d6 100644 --- a/src/FIRFilter.h +++ b/src/FIRFilter.h @@ -65,7 +65,7 @@ public: protected: - int internal_process(Buffer* const dataIn, Buffer* dataOut); + virtual int internal_process(Buffer* const dataIn, Buffer* dataOut); void load_filter_taps(const std::string &tapsFile); std::string m_taps_file; diff --git a/src/GainControl.cpp b/src/GainControl.cpp index 9eb1678..f363d20 100644 --- a/src/GainControl.cpp +++ b/src/GainControl.cpp @@ -69,6 +69,8 @@ GainControl::GainControl(size_t framesize, RC_ADD_PARAMETER(digital, "Digital Gain"); RC_ADD_PARAMETER(mode, "Gainmode (fix|max|var)"); RC_ADD_PARAMETER(var, "Variance setting for gainmode var (default: 4)"); + + start_pipeline_thread(); } GainControl::~GainControl() diff --git a/src/ModPlugin.cpp b/src/ModPlugin.cpp index 34ad797..74db5f9 100644 --- a/src/ModPlugin.cpp +++ b/src/ModPlugin.cpp @@ -74,10 +74,11 @@ int ModOutput::process( PipelinedModCodec::PipelinedModCodec() : ModCodec(), + m_number_of_runs(0), m_input_queue(), m_output_queue(), - m_number_of_runs(0), - m_thread(&PipelinedModCodec::process_thread, this) + m_running(false), + m_thread() { } @@ -89,6 +90,11 @@ PipelinedModCodec::~PipelinedModCodec() } } +void PipelinedModCodec::start_pipeline_thread() +{ + m_thread = std::thread(&PipelinedModCodec::process_thread, this); +} + int PipelinedModCodec::process(Buffer* dataIn, Buffer* dataOut) { if (!m_running) { diff --git a/src/ModPlugin.h b/src/ModPlugin.h index f3a8e2a..d3aa780 100644 --- a/src/ModPlugin.h +++ b/src/ModPlugin.h @@ -83,15 +83,20 @@ public: virtual const char* name() = 0; protected: - void process_thread(void); + // Once the instance implementing PipelinedModCodec has been constructed, + // it must call start_pipeline_thread() + void start_pipeline_thread(void); virtual int internal_process(Buffer* const dataIn, Buffer* dataOut) = 0; +private: + size_t m_number_of_runs; + ThreadsafeQueue > m_input_queue; ThreadsafeQueue > m_output_queue; std::atomic m_running; - size_t m_number_of_runs; std::thread m_thread; + void process_thread(void); }; -- cgit v1.2.3