@@ -112,25 +112,23 @@ void Session::ClearBackgroundThreads()
112
112
{
113
113
LogTrace (" Clearing background threads\n " );
114
114
115
- // Signal our threads to exit
116
- // The sooner we do this, the faster they'll exit.
117
- m_shuttingDown = true ;
118
-
119
115
// Stop the trigger so there's no pending waveforms
120
- StopTrigger ();
116
+ StopTrigger (true );
117
+
118
+ // Shut down instrument threads.
119
+ // This has to happen before we terminate the WaveformThread, to avoid waveforms getting stuck
120
+ // which have been acquired but not processed
121
+ for (auto it : m_instrumentStates)
122
+ it.second ->Close ();
121
123
122
124
// Clear our trigger state
123
125
// Important to signal the WaveformProcessingThread so it doesn't block waiting on response that's not going to come
124
- m_triggerArmed = false ;
125
126
g_waveformReadyEvent.Clear ();
126
127
g_rerenderDoneEvent.Clear ();
127
128
g_waveformProcessedEvent.Signal ();
128
129
129
- // Shut down instrument threads
130
- for (auto it : m_instrumentStates)
131
- it.second ->Close ();
132
-
133
- // Block until our processing threads exit
130
+ // Signal our other worker threads to exit, then wait until they do so
131
+ m_shuttingDown = true ;
134
132
if (m_waveformThread)
135
133
m_waveformThread->join ();
136
134
m_waveformThread = nullptr ;
@@ -178,10 +176,25 @@ void Session::Clear()
178
176
// Might be redundant.
179
177
lock_guard<mutex> lock2 (m_scopeMutex);
180
178
181
- // Clear history before destroying scopes.
182
- // This ordering is important since waveforms removed from history get pushed into the WaveformPool of the scopes,
183
- // so the scopes must not have been destroyed yet.
184
- m_history.clear ();
179
+ // Add any latecomer waveforms to history to make sure we know who owns them
180
+ if (g_waveformReadyEvent.Peek ())
181
+ {
182
+ LogTrace (" Found late waveform, adding to history before clearing it\n " );
183
+
184
+ vector<shared_ptr<Oscilloscope>> scopes;
185
+ set<shared_ptr<TriggerGroup>> groups;
186
+ {
187
+ lock_guard<mutex> lock3 (m_recentlyTriggeredScopeMutex);
188
+ for (auto scope : m_recentlyTriggeredScopes)
189
+ scopes.push_back (scope);
190
+ m_recentlyTriggeredScopes.clear ();
191
+
192
+ groups = m_recentlyTriggeredGroups;
193
+ m_recentlyTriggeredGroups.clear ();
194
+
195
+ m_history.AddHistory (scopes);
196
+ }
197
+ }
185
198
186
199
// Delete scopes once we've terminated the threads
187
200
// Detach waveforms before we destroy the scope, since history owns them
@@ -197,6 +210,11 @@ void Session::Clear()
197
210
}
198
211
}
199
212
213
+ // Clear history before destroying scopes (but after detaching waveforms)
214
+ // This ordering is important since waveforms removed from history get pushed into the WaveformPool of the scopes,
215
+ // so the scopes must not have been destroyed yet.
216
+ m_history.clear ();
217
+
200
218
m_oscilloscopes.clear ();
201
219
m_psus.clear ();
202
220
m_loads.clear ();
0 commit comments