Hi, > From: "Niall Douglas" <s_sourcefo...@nedprod.com> > On 10 Apr 2013 at 13:48, Holger Joukl wrote: > > > > If you don't have C++11 in your C++, Boost provides an okay partial > > > implementation of C++11 exception support.
I'm currently using gcc 4.6.1 which supports the necessary features using -std=c++0x but also Solaris Studio 12.2 which doesn't so I'd need the Boost implementation. > > I'll look into this. This would then mean instrumenting some object with a > > place > > to store the caught exception to re-raise upon reentry from C to C++. > > I take it this would then do much the same as my approach sketched above > > but > > "safer and sounder". > > There is always the trick of keeping a hash table keyed on thread id > and call function depth. In fact it could even be made lock free and > wait free with Boost v1.53's new lock and wait free queue > implementations. A bit of a simplified example version using Boost's partial C++11 exception support would then be s.th. like: 0 $ cat dispatch_main_exception_map.cpp // File: dispatch_main_exception_map.cpp #include <iostream> #include <exception> #include <stdexcept> #include <pthread.h> // header-only: #include <boost/unordered_map.hpp> // header-only: #include <boost/exception_ptr.hpp> #include "dispatch.h" // the global per-thread exception storage boost::unordered_map<pthread_t, boost::exception_ptr> exception_map; void callback(cb_arg_t arg) { std::cout << "--> CPP callback" << arg << std::endl; std::cout << "<-- CPP callback" << arg << std::endl; } // this callback raises an exception void callback_with_exception(cb_arg_t arg) { std::cout << "--> exception-throwing CPP callback" << arg << std::endl; throw std::runtime_error("throwing up"); std::cout << "<-- exception-throwing CPP callback" << arg << std::endl; } // this callback raises an exception, catches it and stores it in the // global (thread, exception)-map void guarded_callback_with_exception(cb_arg_t arg) { std::cout << "--> guarded exception-throwing CPP callback" << arg << std::endl; try { throw std::runtime_error("throwing up"); } catch (...) { std::cout << "storing exception in exception map" << std::endl; pthread_t current_thread = pthread_self(); exception_map[current_thread] = boost::current_exception(); exception_map.erase(current_thread); //global_exception_holder = boost::current_exception(); } std::cout << "<-- guarded exception-throwing CPP callback" << arg << std::endl; } int main(void) { std::cout << "--> CPP main" << std::endl; cb_arg_t s = "CPP main callback argument"; std::cout << std::endl; invoke(&callback, s); std::cout << std::endl; invoke(&guarded_callback_with_exception, s); pthread_t current_thread = pthread_self(); if (exception_map.find(current_thread) != exception_map.end()) { try { std::cout << "rethrowing exception from exception map" << std::endl; boost::rethrow_exception(exception_map[current_thread]); } catch (const std::exception& exc) { std::cout << "caught callback exception: " << exc.what() << std::endl; } } std::cout << std::endl; try { invoke(&callback_with_exception, s); } catch (const std::exception& exc) { std::cout << "caught callback exception: " << exc.what() << std::endl; } std::cout << std::endl; std::cout << "<-- CPP main" << std::endl; return 0; } Which doesn't respect call function depth (how would I do that?) and doesn't use a queue; I suppose you mean using the lockfree queue for threadsafe access to the hash table. I think I don't even need that for my use case as I basically - call dispatch on a Boost.Python wrapped object - which invokes the C libs dispatcher function - which invokes the registered callbacks (these will usually be implemented in Python) i.e. the same thread that produced the exception will need to handle it. So what I have to make sure is that - no exception can propagate back to the C lib - I recognize an exception has happened, in the initial dispatch method in the same thread, to re-raise it and let Boost.Python translate it back to Python It looks like getting at the thread ID is also not too portable. This is something that the simple solution of using (abusing?) the Python per-thread exception indicator would avoid. Thanks for the valuable hints! Holger Landesbank Baden-Wuerttemberg Anstalt des oeffentlichen Rechts Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz HRA 12704 Amtsgericht Stuttgart _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig