Problem
I want to stop the entire program process on a special event from GUI (Qt 5.15.2), except the GUI thread, and show an error message dialog and terminate the program.
1) Problem With Getting All Running Threads
I need to put all other running threads in sleep before they cause some problems like Segmentation Fault. With POSIX Thread APIs and MS-Windows APIs, we have a proper API for getting a list of all running threads. But I don't find a similar one from STL. Is there any cross-platform API (even from third-party libraries like Qt or Boost)? Or I must implement using platform-specific APIs?
2) Problem With Putting All Running Threads In Sleep
After getting the running threads, how could I put them to sleep while they are in the middle of some sort of blocking operations? It's possible?
CodePudding user response:
In general what you are asking for is not possible, at least not without keeping your own list of active threads and co-operating with them to achieve that result.
For example, if your main/GUI thread keeps its own list of active threads (which it appends to whenever it spawns a thread, and removes from whenever it joins an exited thread), it could also maintain a list of QMutex
objects (one per thread), and to "pause all threads" it could acquire every QMutex
in the list. That, by itself, wouldn't affect the threads at all, but if you had added code to each thread to periodically acquire and then immediately release its QMutex
, then the next time the thread tried to acquire the QMutex
it would block inside the acquire function until the main thread decided to release the QMutex
again.
That said, I don't think that sleeping all running threads is the proper solution to your problem anyway. If your problem is that threads are occasionally crashing when you try to exit your program, the proper solution to that problem is to perform a controlled shutdown: have your main thread ask all of the child threads to go away (via std::atomic<bool>
or pipe()
or socketpair()
or condition-variable or whatever other mechanism is convenient) and then call join()
on each of the child threads before exiting. That way, when the main thread finally does exit, it is guaranteed that no child threads are running anymore, and thus there is no race condition possible between the main thread's cleaning up of resources and child threads trying to still use them.
If your child threads are stuck inside blocking calls, that can be a problem, since the child threads can't exit until after their blocking calls have returned, and the main thread can't complete all of its calls to join()
until all of the child threads have exited. One way to deal with that problem would be to put timeouts on the blocking calls, so that the child threads will periodically be able to unblock and see if they need to exit; that's a bit ugly, though, so in my programs I try to use only non-blocking I/O instead (e.g. have the child threads only block inside select()
or poll()
, and when the main thread wants them to go away, it sends a byte on a pipe()
that the child thread is selecting-for-read-ready on, to notify the child thread that it is time to exit ASAP)