Skip to content

Commit 4f87b4f

Browse files
Merge pull request #16064 from daschuer/valigrind_analyzerthread
Fix killing Analyzis worker threads during shutdown, possible data loss.
2 parents 0cce8fc + 9fbbf7b commit 4f87b4f

13 files changed

Lines changed: 58 additions & 55 deletions

src/analyzer/trackanalysisscheduler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ TrackAnalysisScheduler::TrackAnalysisScheduler(
9292

9393
TrackAnalysisScheduler::~TrackAnalysisScheduler() {
9494
kLogger.debug() << "Destroying";
95+
// Here the workers in m_workers are deleted after waiting for the associated thread is finished
9596
}
9697

9798
void TrackAnalysisScheduler::emitProgressOrFinished() {
@@ -228,7 +229,7 @@ void TrackAnalysisScheduler::onWorkerThreadProgress(
228229
DEBUG_ASSERT(!trackId.isValid());
229230
DEBUG_ASSERT(analyzerProgress == kAnalyzerProgressUnknown);
230231
worker.onThreadExit();
231-
DEBUG_ASSERT(!worker);
232+
DEBUG_ASSERT(!worker.hasThread());
232233
break;
233234
default:
234235
DEBUG_ASSERT(!"Unhandled signal from worker thread");

src/analyzer/trackanalysisscheduler.h

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,62 +80,72 @@ class TrackAnalysisScheduler : public QObject {
8080
// that runs the TrackAnalysisScheduler.
8181
class Worker {
8282
public:
83-
explicit Worker(AnalyzerThread::Pointer thread = AnalyzerThread::NullPointer())
84-
: m_thread(std::move(thread)),
85-
m_analyzerProgress(kAnalyzerProgressUnknown) {
83+
explicit Worker(AnalyzerThread::Pointer pThread = AnalyzerThread::NullPointer())
84+
: m_pThread(std::move(pThread)),
85+
m_analyzerProgress(kAnalyzerProgressUnknown) {
8686
}
8787
Worker(const Worker&) = delete;
8888
Worker(Worker&&) = default;
8989

90-
operator bool() const {
91-
return static_cast<bool>(m_thread);
90+
~Worker() {
91+
if (m_pThread) {
92+
m_pThread->stop();
93+
bool success = m_pThread->wait(5000); // 5 s
94+
DEBUG_ASSERT(success);
95+
m_pThread->wait();
96+
delete m_pThread.release();
97+
}
98+
}
99+
100+
bool hasThread() const {
101+
return static_cast<bool>(m_pThread);
92102
}
93103

94104
AnalyzerThread* thread() const {
95-
DEBUG_ASSERT(m_thread);
96-
return m_thread.get();
105+
DEBUG_ASSERT(m_pThread);
106+
return m_pThread.get();
97107
}
98108

99109
AnalyzerProgress analyzerProgress() const {
100110
return m_analyzerProgress;
101111
}
102112

103113
bool submitNextTrack(const AnalyzerTrack& track) {
104-
DEBUG_ASSERT(m_thread);
105-
return m_thread->submitNextTrack(std::move(track));
114+
DEBUG_ASSERT(m_pThread);
115+
return m_pThread->submitNextTrack(std::move(track));
106116
}
107117

108118
void suspendThread() {
109-
if (m_thread) {
110-
m_thread->suspend();
119+
if (m_pThread) {
120+
m_pThread->suspend();
111121
}
112122
}
113123

114124
void resumeThread() {
115-
if (m_thread) {
116-
m_thread->resume();
125+
if (m_pThread) {
126+
m_pThread->resume();
117127
}
118128
}
119129

120130
void stopThread() {
121-
if (m_thread) {
122-
m_thread->stop();
131+
if (m_pThread) {
132+
m_pThread->stop();
123133
}
124134
}
125135

126136
void onAnalyzerProgress(AnalyzerProgress analyzerProgress) {
127-
DEBUG_ASSERT(m_thread);
137+
DEBUG_ASSERT(m_pThread);
128138
m_analyzerProgress = analyzerProgress;
129139
}
130140

131141
void onThreadExit() {
132-
DEBUG_ASSERT(m_thread);
133-
m_thread.reset();
142+
DEBUG_ASSERT(m_pThread);
143+
m_pThread.reset();
134144
m_analyzerProgress = kAnalyzerProgressUnknown;
135145
}
136146

137147
private:
138-
AnalyzerThread::Pointer m_thread;
148+
AnalyzerThread::Pointer m_pThread;
139149
AnalyzerProgress m_analyzerProgress;
140150
};
141151

src/control/controlobject.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ ControlObject::ControlObject(const ConfigKey& key,
4141
ControlObject::~ControlObject() {
4242
DEBUG_ASSERT(m_pControl);
4343
const bool success = m_pControl->resetCreatorCO(this);
44-
Q_UNUSED(success);
4544
DEBUG_ASSERT(success);
4645
}
4746

src/library/analysis/analysisfeature.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ AnalysisFeature::AnalysisFeature(
5555
m_title(m_baseTitle) {
5656
}
5757

58+
AnalysisFeature::~AnalysisFeature() {
59+
// We need to delete m_pTrackAnalysisScheduler here immediately synchronously,
60+
// waiting for pending threads to have finished, to not kill them during exit
61+
delete m_pTrackAnalysisScheduler.release();
62+
}
63+
5864
void AnalysisFeature::resetTitle() {
5965
m_title = m_baseTitle;
6066
emit featureIsLoading(this, false);

src/library/analysis/analysisfeature.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class AnalysisFeature : public LibraryFeature {
1818
public:
1919
AnalysisFeature(Library* pLibrary,
2020
UserSettingsPointer pConfig);
21-
~AnalysisFeature() override = default;
21+
~AnalysisFeature() override;
2222

2323
QVariant title() override {
2424
return m_title;

src/library/dao/autodjcratesdao.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@ namespace {
4343
constexpr int kLeastPreferredPercent = 15;
4444

4545
// These consts are only used for DEBUG_ASSERTs
46-
#ifdef MIXXX_DEBUG_ASSERTIONS_ENABLED
4746
constexpr int kLeastPreferredPercentMin = 0;
4847
constexpr int kLeastPreferredPercentMax = 50;
49-
#endif
5048

5149
int bounded_rand(int highest) {
5250
return QRandomGenerator::global()->bounded(highest);

src/mixer/playermanager.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,9 @@ PlayerManager::~PlayerManager() {
151151
m_samplers.clear();
152152
m_microphones.clear();
153153
m_auxiliaries.clear();
154-
155-
if (m_pTrackAnalysisScheduler) {
156-
m_pTrackAnalysisScheduler->stop();
157-
m_pTrackAnalysisScheduler.reset();
158-
}
154+
// We need to delete m_pTrackAnalysisScheduler here immediately synchronously,
155+
// waiting for pending threads to have finished, to not kill them during exit
156+
delete m_pTrackAnalysisScheduler.release();
159157
}
160158

161159
void PlayerManager::bindToLibrary(Library* pLibrary) {

src/qml/qmlwaveformoverview.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ void QmlWaveformOverview::slotTrackLoaded(TrackPointer pTrack) {
7676
}
7777

7878
void QmlWaveformOverview::slotTrackLoading(TrackPointer pNewTrack, TrackPointer pOldTrack) {
79-
Q_UNUSED(pOldTrack); // only used in DEBUG_ASSERT
8079
DEBUG_ASSERT(m_pCurrentTrack == pOldTrack);
8180
setCurrentTrack(pNewTrack);
8281
}

src/sources/soundsourcemp3.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,11 @@ void logFrameHeader(QDebug logger, const mad_header& madHeader) {
105105
<< "flags:" << formatHeaderFlags(madHeader.flags);
106106
}
107107

108-
inline bool isUnrecoverableError(mad_error error) {
108+
bool isUnrecoverableError(mad_error error) {
109109
return (MAD_ERROR_NONE != error) && !MAD_RECOVERABLE(error);
110110
}
111111

112-
#ifndef MIXXX_DEBUG_ASSERTIONS_ENABLED
113-
[[maybe_unused]]
114-
#endif
115-
inline bool
116-
hasUnrecoverableError(const mad_stream* pMadStream) {
112+
bool hasUnrecoverableError(const mad_stream* pMadStream) {
117113
if (pMadStream) {
118114
return isUnrecoverableError(pMadStream->error);
119115
}

src/track/beats.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ Beats::ConstIterator Beats::ConstIterator::operator+=(Beats::ConstIterator::diff
6060
}
6161

6262
DEBUG_ASSERT(n > 0);
63-
#ifdef MIXXX_DEBUG_ASSERTIONS_ENABLED
64-
const auto origValue = m_value;
65-
#endif
63+
const audio::FramePos origValue = m_value;
6664

6765
// Detect integer overflow in `m_beatOffset + n`
6866
const int maxBeatOffset = std::numeric_limits<Beats::ConstIterator::difference_type>::max();
@@ -108,9 +106,7 @@ Beats::ConstIterator Beats::ConstIterator::operator-=(Beats::ConstIterator::diff
108106
}
109107

110108
DEBUG_ASSERT(n > 0);
111-
#ifdef MIXXX_DEBUG_ASSERTIONS_ENABLED
112-
const auto origValue = m_value;
113-
#endif
109+
const audio::FramePos origValue = m_value;
114110

115111
// Detect integer overflow
116112
const int minBeatOffset = std::numeric_limits<Beats::ConstIterator::difference_type>::lowest();

0 commit comments

Comments
 (0)