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