简体   繁体   中英

FATAL: exception not rethrown in c++

I am trying to understand the usage of pthread_cancel on linux environment in c++. But i am getting below runtime problem.

class A {
    public:
        A(){cout<<"constructor\n";}
        ~A(){cout<<"destructor\n";}
};
void* run(void* data) {
    A a;
    while(1) {
        //sleep(1);
        cout<<"while\n";
    }
}
int main() {
    pthread_t pid;
    pthread_create(&pid,NULL,run,NULL);
    sleep(2);;
    pthread_cancel(pid);
    cout<<"Canceled\n";
    pthread_exit(0);
}

Output:

constructor 
while 
while 
...
while 
while 
Canceled 
FATAL: exception not rethrown 
Aborted (core dumped)

Core file analysis:

(gdb) where
#0  0x00000036e8c30265 in raise () from /lib64/libc.so.6
#1  0x00000036e8c31d10 in abort () from /lib64/libc.so.6
#2  0x00000036e9c0d221 in unwind_cleanup () from /lib64/libpthread.so.0
#3  0x00000036fa69042b in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) () from /usr/lib64/libstdc++.so.6
#4  0x00000000004009c5 in run(void*) ()
#5  0x00000036e9c0677d in start_thread () from /lib64/libpthread.so.0
#6  0x00000036e8cd49ad in clone () from /lib64/libc.so.6

But, If i uncomment the sleep(1) in thread function run, I am getting below output.

constructor 
while 
Canceled 
destructor

Could you please explain me why the program is giving "FATAL: exception not rethrown" in 1st case and not in 2nd? And please explain in detail why pthread_cancel is safer than pthread_kill with an example?

Sorry to be the bearer of bad news but it is very hard to get pthread_cancel to work properly in C++ in Linux.

The reason is that the pthread_cancel method implementation in Linux is absolutely horrid. In particular it causes an exception ( abi::__forced_unwind as of the time I'm writing this) to be thrown. This probably is fine in a C program, but in C++ it makes it very difficult to handle the thread cancellation properly. In particular if you have any code that eats exceptions (such as catch (...) ) this internal exception will handled and not passed up the stack the way it needs to be. In this case you will see the error message that you are seeing.

That said, I don't see what in your code would be "eating" this exception, but I suspect it is something of that nature that is causing the problem.

In your particular example this is easy to work around by using a flag or something similar to note when you want to exit and not call pthread_cancel. Unfortunately that makes sleep more complex (you need to call it multiple times with small intervals in order to check the flag) and calls to accept nearly impossible (you have to make a connection to the port from another thread or process to force accept to exit so you can check the variable). There is a long discussion on the problems with thread cancellation in general ( https://lwn.net/Articles/683118/ ) but given that macOS (and presumably other non-Linux "unixes") seem to handle it well, I really think that the Linux implementation could be done better. But until that is done, pthread_cancel will remain very difficult to use.

My guess is that this has to do with cancellation points. New threads have cancellation type PTHREAD_CANCEL_DEFERRED by default. That means that pthread_cancel won't do anything until the thread hits one of the predefined cancellation points. sleep is one of the defined cancellation points, but std::cout::operator<< is not (pthreads' man page lists all of them). Thus when you have your sleep commented out, the thread never hits a cancellation point and pthreads throws a fit. You may be able to use pthread_setcanceltype to set the thread to PTHREAD_CANCEL_ASYNCHRONOUS , but that causes issues on my system at least.

Your best bet is probably to use std::thread instead of dealing with pthreads directly. That library is actually designed to work correctly with C++.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM