MCPcopy Create free account
hub / github.com/HaxeFoundation/hxcpp / WaitForAllThreadsToStop

Method WaitForAllThreadsToStop

src/hx/Debugger.cpp:188–250  ·  view source on GitHub ↗

Make best effort to wait until all threads are stopped

Source from the content-addressed store, hash-verified

186
187 // Make best effort to wait until all threads are stopped
188 static void WaitForAllThreadsToStop()
189 {
190 // Make a "best effort" in the face of threads that could do arbitrary
191 // things to make the "break all" not complete successfully. Threads
192 // can hang in system calls indefinitely, and can spawn new threads
193 // continuously that themselves do the same. Don't try to be perfect
194 // and guarantee that all threads have stopped, as that could mean
195 // waiting a long time in pathological cases or even forever in really
196 // pathological cases. Just make a best effort and if the break
197 // doesn't break everything, the user will know when they go to list
198 // all thread stacks and can try the break again.
199
200 // Copy the thread numbers out. This is because we really don't want
201 // to hold the lock during the entire process as this could block
202 // threads from actually evaluating breakpoints.
203 std::vector<int> threadNumbers;
204 gMutex.lock();
205 std::list<DebuggerContext *>::iterator iter = gList.begin();
206 while (iter != gList.end()) {
207 DebuggerContext *stack = *iter++;
208 if (stack->mThreadNumber == g_debugThreadNumber) {
209 continue;
210 }
211 threadNumbers.push_back(stack->mThreadNumber);
212 }
213 gMutex.unlock();
214
215 // Now wait no longer than 2 seconds total for all threads to
216 // be stopped. If any thread times out, then stop immediately.
217 int size = threadNumbers.size();
218 // Each time slice is 1/10 of a second. Yeah there's some slop here
219 // because no time is accounted for the time spent outside of sem
220 // waiting. If there were good portable time APIs easily available
221 // within hxcpp I'd use them ...
222 int timeSlicesLeft = 20;
223 HxSemaphore timeoutSem;
224 int i = 0;
225 while (i < size) {
226 gMutex.lock();
227 DebuggerContext *stack = gMap[threadNumbers[i]];
228 if (!stack) {
229 // The thread went away while we were working!
230 gMutex.unlock();
231 i += 1;
232 continue;
233 }
234 if (stack->mWaiting) {
235 gMutex.unlock();
236 i += 1;
237 continue;
238 }
239 gMutex.unlock();
240 if (timeSlicesLeft == 0) {
241 // The 2 seconds have expired, give up
242 return;
243 }
244 // Sleep for 1/10 of a second on a semaphore that will never
245 // be Set.

Callers

nothing calls this directly

Calls 2

WaitSecondsMethod · 0.80
sizeMethod · 0.45

Tested by

no test coverage detected