230703 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
14
auto 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

thread pool

thread pool is to better and easier manage the computing resource