I try to inject the exception to thread using signals, but some times the exception is not get caught. For example the following code:
void _sigthrow(int sig)
{
throw runtime_error(strsignal(sig));
}
struct sigaction sigthrow = {{&_sigthrow}};
void* thread1(void*)
{
sigaction(SIGINT,&sigthrow,NULL);
try
{
while(1) usleep(1);
}
catch(exception &e)
{
cerr << "Thread1 catched " << e.what() << endl;
}
};
void* thread2(void*)
{
sigaction(SIGINT,&sigthrow,NULL);
try
{
while(1);
}
catch(exception &e)
{
cerr << "Thread2 catched " << e.what() << endl; //never goes here
}
};
If I try to execute like:
int main()
{
pthread_t p1,p2;
pthread_create( &p1, NULL, &thread1, NULL );
pthread_create( &p2, NULL, &thread2, NULL );
sleep(1);
pthread_kill( p1, SIGINT);
pthread_kill( p2, SIGINT);
sleep(1);
return EXIT_SUCCESS;
}
I get the following output:
Thread1 catched Interrupt
terminate called after throwing an instance of 'std::runtime_error'
what(): Interrupt
Aborted
How can I make second threat catch exception?
Is there better idea about injecting exceptions?
G++ assumes that exceptions can only be thrown from function calls. If you’re going to violate this assumption (eg, by throwing them from signal handlers), you need to pass
-fnon-call-exceptionsto G++ when building your program.Note, however that this causes G++ to:
This means that exceptioning out from the middle of some random code is NEVER safe. You can only except out of
SIGSEGV,SIGBUS, andSIGFPE, and only if you pass-fnon-call-exceptionsand they were triggered due to a fault in the running code. The only reason this worked on thread 1 is because, due to the existence of theusleep()call, G++ was forced to assume that it might throw. With thread 2, G++ can see that no trapping instruction was present, and eliminate the try-catch block.You may find the pthread cancellation support more akin to what you need, or otherwise just add a test like this somewhere: