У меня есть поток обработчика выхода, ожидающий условия, когда рабочий поток выполнит свою работу. Сигнализация осуществляется из деструктора рабочего потока.
Ниже приведен код потока обработчика выхода.
void Class::TaskExitHandler::run() throw()
{
while( ! isInterrupted() ) {
_book->_eot_cond.wait(); // Waiting on this condition
{
CLASS_NAMESPACE::Guard<CLASS_NAMESPACE::FastLock> eguard(_book->_exitlist_lock);
list<TaskGroupExecutor*>::const_iterator itr = _book->_exited_tasks.begin();
for( ; itr != _book->_exited_tasks.end(); itr++ ) {
(*itr)->join();
TRACER(TRC_DEBUG)<< "Deleting exited task:" << (*itr)->getLoc() << ":"
<< (*itr)->getTestID() << ":" << (*itr)->getReportName() << endl;
delete (*itr);
}
_book->_exited_tasks.clear();
}
_book->executeAny();
}
}
}
Теперь было замечено, что когда рабочий поток перехватывает любое исключение (поднятое с нижнего уровня), этот поток продолжается и немедленно запускает ядро с кодом выхода 134, то есть SIGABRT.
Трассировка стека выглядит следующим образом:
#0 0x0000005555f49b4c in raise () from /lib64/libc.so.6
#1 0x0000005555f4b568 in abort () from /lib64/libc.so.6
#2 0x0000005555d848b4 in __gnu_cxx::__verbose_terminate_handler () from /usr/lib64/libstdc++.so.6
#3 0x0000005555d82210 in ?? () from /usr/lib64/libstdc++.so.6
#4 0x0000005555d82258 in std::terminate () from /usr/lib64/libstdc++.so.6
#5 0x0000005555d82278 in ?? () from /usr/lib64/libstdc++.so.6
#6 0x0000005555d81b18 in __cxa_call_unexpected () from /usr/lib64/libstdc++.so.6
#7 0x0000000120047898 in Class::TaskExitHandler::run ()
#8 0x000000012001cd38 in commutil::ThreadBase::thread_proxy ()
#9 0x0000005555c6e438 in start_thread () from /lib64/libpthread.so.0
#10 0x0000005555feed6c in __thread_start () from /lib64/libc.so.6
Backtrace stopped: frame did not save the PC
Таким образом, кажется, что эта функция run(), которая указывает, что она не будет генерировать никаких исключений, используя спецификацию «throw()», вызывает исключение (из кадра 4). Согласно различным ссылкам на __cxa_call_unexpected(), трассировка стека отображает типичное поведение компилятора для прерывания, когда в функции со спецификацией «throw()» возникает исключение. Я прав с анализом проблемы?
Для проверки я добавил в этот метод функцию try catch и напечатал сообщение об исключении. Теперь процесс не запустился. Сообщение об исключении было таким же, как и сообщение, перехваченное рабочим потоком. Мой вопрос: как этот поток получает доступ к исключению, пойманному другим? Имеют ли они общую структуру данных, связанную с обработкой исключений?
Пожалуйста, пролейте свет на это. Это довольно озадачивает..
Примечание. В соответствии с трассировкой стека call_unexpected возникает сразу после вызова run(). Это усиливает мои сомнения в том, что стек исключений или данные каким-то образом являются общими. Но не нашел никаких ссылок на это поведение.