Cpp multi-threading exception on Windows
在工作的时候遇到了exception如果发生在std::thread里面整个程序会直接崩溃的问题。
Conclusion
感觉要么自己在thread里处理好exception,或者自己包装一下thread(配合promise使用),要么用更高级的API,可以返回运行结果或者exception。
When exception happens in a running std::thread
if use std::thread, an exception occurs and not catched inside thread > If no matching handler is found, the function std::terminate() is called > https://stackoverflow.com/a/7272147 > https://en.cppreference.com/w/cpp/thread/thread
By default, terminate() will call abort() > https://cplusplus.com/reference/exception/terminate/
- cannot catch exception outside the thread where the exception happens > No you most definitely cannot catch an exception outside of its "thread or origin". The exception catching depends on stack unwinding, and stack is fundamentally thread-specific. > https://stackoverflow.com/a/7272147
didn't find a source for "exception catching depends on stack unwinding"
- use std::async instead of std::thread >
https://stackoverflow.com/a/7273925
1
2
3
4
5
6
7
8
9
10
11
12
13
14auto run = []() -> T // T may be void as above
{
// may throw
return /* some T */;
};
auto launched = std::async(run);
// launched has type std::future<T>
// may throw here; nothing bad happens
// expression has type T and may throw
// will throw whatever was originally thrown in run
launched.get();
this way we can get the exception by launched.get()
in
the parent thread. if not call get(), exception will be ignored (I
tested).
However, async() does not guarantee to use a separate thread > https://en.cppreference.com/w/cpp/thread/async
- maybe use std::thread with std::promise and std::future, create a wrapper > https://en.cppreference.com/w/cpp/thread/promise
Use Threading API (Microsoft's PPL) rather than plain std::thread
https://stackoverflow.com/a/25221591
std::async also use PPL API?
https://stackoverflow.com/a/36914984
This answer also says concurrency::task
has lower
efficiency, compared to self-made thread pool with
std::thread
and std::promise
.
While, in MS document, it only says async use Windows thread pool, and non-conforming with C++ standard
The C++ standard states that if policy is launch::async, the function creates a new thread. However the Microsoft implementation is currently non-conforming. It obtains its threads from the Windows ThreadPool, which in some cases may provide a recycled thread rather than a new one. This means that the launch::async policy is implemented as launch::async|launch::deferred. Another implication of the ThreadPool-based implementation is that there's no guarantee that thread-local variables will be destroyed when the thread completes. If the thread is recycled and provided to a new call to async, the old variables will still exist. We recommend that you don't use thread-local variables with async. https://learn.microsoft.com/en-us/cpp/standard-library/future-functions?view=msvc-170#async