id,summary,reporter,owner,description,type,status,milestone,component,version,severity,resolution,keywords,cc 10093,"Exceptions ""teleport"" between coroutines when switching inside catch",snaury@…,olli,"Sorry for using coroutines v1 API, but the actual API doesn't matter as much as the result and the reason for it. Consider the following program: {{{#!cpp #define BOOST_COROUTINES_V1 #include #include #include typedef boost::coroutines::coroutine coro_t; void mycoro(coro_t::caller_type& caller) { std::cout << ""calling caller..."" << std::endl; caller(); try { try { throw std::runtime_error(""mycoro exception""); } catch(const std::exception& e) { std::cout << ""calling caller in the catch block..."" << std::endl; caller(); std::cout << ""rethrowing mycoro exception..."" << std::endl; throw; } } catch (const std::exception& e) { std::cout << ""mycoro caught: "" << e.what() << std::endl; } std::cout << ""exiting mycoro..."" << std::endl; } int main(int argc, char** argv) { coro_t callee(mycoro); try { try { throw std::runtime_error(""main exception""); } catch(const std::exception& e) { std::cout << ""calling callee in the catch block..."" << std::endl; callee(); std::cout << ""rethrowing main exception..."" << std::endl; throw; } } catch (const std::exception& e) { std::cout << ""main caught: "" << e.what() << std::endl; } std::cout << ""calling callee one last time..."" << std::endl; callee(); std::cout << ""exiting main..."" << std::endl; return 0; } }}} When compiled with gcc it causes the following output: {{{ calling caller... calling callee in the catch block... calling caller in the catch block... rethrowing main exception... main caught: mycoro exception calling callee one last time... rethrowing mycoro exception... mycoro caught: main exception exiting mycoro... exiting main... }}} Which shows that boost coroutines are unsafe in the presence of current exceptions, since in that case exceptions ""teleport"" between coroutines in weird ways. The problem here is that caught exceptions are saved in per-thread globals according to ABI, see: mentorembedded.github.io/cxx-abi/abi-eh.html (struct __cxa_eh_globals). It contains two very important fields, pointer to which can be obtained with __cxx_get_globals() or with __cxx_get_globals_fast() and check for null result (though the latter is not as reliable). Whenever coroutines switch they should save and restore those fields to properly support exceptions and avoid current exception bleeding between coroutines. This ABI is supported by both gcc and clang, though I'm not sure since which version.",Bugs,closed,To Be Determined,context,Boost 1.54.0,Problem,wontfix,,