2

Let's say we have two running threads that both would throw exceptions and there are exception handlers in these threads. Would C++ be able to handle that, not running into terminated or undefined behavior.

Is it correct that exception belongs to per thread, and each thread can have no more than one exception at a time?

henryyao
  • 1,758
  • 6
  • 23
  • 37
  • Are you *catching* any of the exceptions? – Kerrek SB Nov 01 '18 at 15:08
  • @KerrekSB Yes. edited – henryyao Nov 01 '18 at 15:12
  • How is this question duplicated as "Will main() catch exceptions thrown from threads?" – henryyao Nov 01 '18 at 15:13
  • I have no idea. I'm reopening. – NathanOliver Nov 01 '18 at 15:15
  • Think of an exception as an alternative way for a function call to return. Call/return happens on the stack of a single thread. Same goes for exceptions. (NOTE: I am not enough of a C++ wizard to know what is supposed to happen to a multi-threaded process if the _top-level_ function in one of its several threads throws.) – Solomon Slow Nov 01 '18 at 15:17
  • I would probably say that threads are about *scopes* more than about *threads*, but the latter implies the former (a new thread starts a new scope). Recall that you *can* throw new exceptions even while you're unwinding an existing exception, you just have to catch it before it gets out. In other words, you can (even in a single thread) have arbitrarily many exceptions in flight, but what you require is a well-defined order in which they are caught. – Kerrek SB Nov 01 '18 at 15:18
  • Possible duplicate of [Writing Multithreaded Exception-Safe Code](https://stackoverflow.com/questions/329061/writing-multithreaded-exception-safe-code) – Jean-Baptiste Yunès Nov 01 '18 at 15:39

2 Answers2

1

Is it correct that exception belongs to per thread

That is correct.

and each thread can have no more than one exception at a time?

A thread can have more than one active exception. See int uncaught_exceptions() noexcept:

Detects how many exceptions in the current thread have been thrown or rethrown and not yet entered their matching catch clauses.

E.g.:

#include <iostream>
#include <stdexcept>

void f() {
    throw std::runtime_error("error");
}

struct A {
    ~A() {
        std::cout << "uncaught_exceptions: " << std::uncaught_exceptions() << '\n';
    }
};

struct B {
    ~B() {
        try {
            A a;
            f();
        }
        catch(std::exception&) {}
    }
};

int main() {
    try {
        B b;
        f();
    }
    catch(std::exception&) {}
}

Outputs:

uncaught_exceptions: 2
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
0

The following example shows that the exception handler is using the stack of thread t1 which made a division by zero exception. It means that exception belongs to per thread.

// g++ -std=c++0x -pthread -fnon-call-exceptions main.cpp
#include <iostream>
#include <thread>
#include <signal.h>

void handler(int signo) {
    int handler_local_var;
    std::cout << &handler_local_var << " in stack of handler" << std::endl;
    throw signo;
}

void thread1(std::string msg) {
    int t1_local_var;
    std::cout << &t1_local_var << " in stack of " << msg << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    signal(SIGFPE,handler);
    try { 
        int x = 100 / 0; /* ignore warning: division by zero [-Wdiv-by-zero] */
    }
    catch (...) {
        std::cout << "caught" << std::endl;
    }
    while (1) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
}

void thread2(std::string msg) {
    int t2_local_var;
    std::cout << &t2_local_var << " in stack of " << msg <<  std::endl;
    while (1) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
}

int main() {
    int main_local_var;
    std::cout << &main_local_var << " in stack of main" << std::endl;
    std::thread t1(thread1,"t1");
    std::thread t2(thread2,"t2");
    while (1) {
        std::this_thread::sleep_for(std::chrono::seconds(2)); /* Ctrl-C to stop */
    }
    return 0;
}

Test result:

$ ./a.out 
0x7ffee7fea788 in stack of main
0x7f0b54b92d68 in stack of t2
0x7f0b55393d54 in stack of t1
0x7f0b55393754 in stack of handler
caught
JaeMann Yeh
  • 358
  • 2
  • 9