Why am I losing exceptions with SWIG, C++, python -
i'm going out of mind here. expect catch exceptions in c++ can map them custom exception class in python. python exceptions. cannot catch exceptions inside generated code???
program:
#!/usr/bin/python import os import sys import hpsphal_python prog = os.path.basename(__file__) + ": " try: hal = hpsphal_python.system_getsystem() scs = hal.getstorageclusters() if len(scs) == 0: print >>sys.stderr, prog + "no storage clusters found." os._exit(-1) sc in scs: print "sc: ", sc.getuuid() conts = sc.getcontrollers() c in conts: try: c.setclock() except hpsphal_python.exception e: print "he: ", e.what() except runtimeerror e: print "rt: ", e, e[0] except exception e: print "e: ", e, e[0] os._exit(0) except exception, e: print "e: ", e os._exit(-1) output:
sc: 222367ad-0005-1000-95ab-415a34303736 e: setcontrollerclock setcontrollerclock e: setcontrollerclock setcontrollerclock sc: mxq04205mv_con_0_cluster e: setcontrollerclock setcontrollerclock same code in c++ in fact catch exceptions:
#include "time.h" #include <iostream> #include <map> #include <set> #include <string> #include <exception> #include <boost/foreach.hpp> #include <boost/regex.hpp> #include <boost/thread/thread.hpp> #include "exception.hpp" #include "storagecluster.hpp" #include "controller.hpp" #include "system.hpp" using namespace std; int main (int argc, char *argv[]) { danapi::systemptr dansystem; try { dansystem = danapi::system::getsystem(); } catch(danapi::exception& e) { cerr << "unable initialize danapi" << e.what() << endl; return -1; } try { danapi::storageclusterptrlist danstorageclusters = dansystem->getstorageclusters(); boost_foreach(danapi::storageclusterptr sc, danstorageclusters) { danapi::controllerptrlist danstoragecontrollers = sc->getcontrollers(); boost_foreach(danapi::controllerptr c, danstoragecontrollers) { try { c->setclock(); } catch(danapi::exception& e) { cerr << "hal exception: " << e.what() << endl; } catch(exception& e) { cerr << "standard exception: " << e.what() << endl; } } } } catch(exception& e) { cerr << "unable storage clusters: " << e.what() << endl; } return 0; } output:
hal exception: setcontrollerclock: setclock exception: function failed (1) /jenkins/workspace/ts1.4-hpsphal/storage-lib/src/raptor.cpp: 1100 /jenkins/workspace/ts1.4-hpsphal/storage-lib/src/raptor.cpp: 791 (1) /jenkins/workspace/ts1.4-hpsphal/storage-lib/src/storagecluster_rcim.cpp: 2158 hal exception: setcontrollerclock: setclock exception: function failed (1) /jenkins/workspace/ts1.4-hpsphal/storage-lib/src/raptor.cpp: 1100 /jenkins/workspace/ts1.4-hpsphal/storage-lib/src/raptor.cpp: 791 (1) /jenkins/workspace/ts1.4-hpsphal/storage-lib/src/storagecluster_rcim.cpp: 2158 the players:
custom exception class swig 2.0.12 boost 1.41 throw_exception a snippet generated code:
{ try { (arg1)->setclock(); } catch(danapi::exception& e) { std::cerr << "++++++" << std::endl; } catch(std::exception& e) { std::cerr << "++++++" << std::endl; } catch(boost::exception& e) { std::cerr << "++++++" << std::endl; } catch(...) { std::cerr << "++++++" << std::endl; } } resultobj = swig_py_void(); return resultobj; fail: return null; here's .i file (hdrs macros filled in header files)
%include "stdint.i" %include "stl.i" %include "std_string.i" %include "std_vector.i" %include "std_string.i" %include "std_pair.i" %include "std_set.i" %include "typemaps.i" %apply unsigned long long &output { unsigned long long &firstcharinbuffer }; %apply unsigned long long &output { unsigned long long &nextchar }; %exceptionclass danapi::exception; %exception { try { $action } catch(danapi::exception &e) { swig_python_raise(swig_newpointerobj( (new danapi::exception(static_cast<const danapi::exception&>(e))), swigtype_p_danapi__exception,swig_pointer_own), "exception", swigtype_p_danapi__exception); swig_fail; } } // need define templates shared_ptr<t> before define // various t's below; put in common place various swig interfaces // stay in sync %include "hpsphal_ptrs.i" %{ ${hash_public_headers} using namespace danapi; %} ${percent_public_headers} // need define vector types after we've defined types // themselves; moved common place keep various swig interfaces // in sync %include "hpsphal_vectors.i" i ran code in gdb, "catch throw". saw few exceptions catch internal library. there should have been 3 exceptions thrown library, caught swig code.
this caught internally:
#0 0x000000337c8bccb0 in __cxa_throw () /usr/lib64/libstdc++.so.6 #1 0x00007ffff122a1ac in boost::throw_exception<danapi::exception> (e=...) @ /usr/include/boost/throw_exception.hpp:64 #2 0x00007fffef398841 in danapi::storageclusterfactory::getstoragecontrollertype (this=0x7fffffffd6d0, path="/dev/sg4") @ /home/chchr/src/hpsphal/storage-lib/src/storageclusterfactory.cpp:247 #3 0x00007fffef398aa8 in danapi::storageclusterfactory::createstoragecluster (this=0x7fffffffd6d0, path="/dev/sg4", storclustplist=std::vector of length 1, capacity 1 = {...}, cluster=std::tr1::shared_ptr (empty) 0x0, err=...) @ /home/chchr/src/hpsphal/storage-lib/src/storageclusterfactory.cpp:308 #4 0x00007fffef3a262c in boost::_mfi::cmf4<void, danapi::storageclusterfactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danapi::conststorageclusterptrlist const&, danapi::conststorageclusterptr&, boost::exception_ptr&>::call<danapi::storageclusterfactory const* const, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::tr1::shared_ptr<danapi::storagecluster const>, std::allocator<std::tr1::shared_ptr<danapi::storagecluster const> > > const, std::tr1::shared_ptr<danapi::storagecluster const>, boost::exception_ptr> (this=0x896740, u=@0x896750, b1= "/dev/sg4", b2=std::vector of length 1, capacity 1 = {...}, b3=std::tr1::shared_ptr (empty) 0x0, b4=...) @ /usr/include/boost/bind/mem_fn_template.hpp:547 #5 0x00007fffef3a2466 in boost::_mfi::cmf4<void, danapi::storageclusterfactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danapi::conststorageclusterptrlist const&, danapi::conststorageclusterptr&, boost::exception_ptr&>::operator()<danapi::storageclusterfactory const*> ( this=0x896740, u=@0x896750, a1="/dev/sg4", a2=std::vector of length 1, capacity 1 = {...}, a3=std::tr1::shared_ptr (empty) 0x0, a4=...) @ /usr/include/boost/bind/mem_fn_template.hpp:556 #6 0x00007fffef3a21d4 in boost::_bi::list5<boost::_bi::value<danapi::storageclusterfactory const*>, boost::_bi::value<char*>, boost::reference_wrapper<std::vector<std::tr1::shared_ptr<danapi::storagecluster const>, std::allocator<std::tr1::shared_ptr<danapi::storagecluster const> > > >, boost::reference_wrapper<std::tr1::shared_ptr<danapi::storagecluster const> >, boost::reference_wrapper<boost::exception_ptr> >::operator()<boost::_mfi::cmf4<void, danapi::storageclusterfactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danapi::conststorageclusterptrlist const&, danapi::conststorageclusterptr&, boost::exception_ptr&>, boost::_bi::list0> (this=0x896750, f=..., a=...) @ /usr/include/boost/bind/bind.hpp:518 #7 0x00007fffef3a1e0d in boost::_bi::bind_t<void, boost::_mfi::cmf4<void, danapi::storageclusterfactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danapi::conststorageclusterptrlist const&, danapi::conststorageclusterptr&, boost::exception_ptr&>, boost::_bi::list5<boost::_bi::value<danapi::storageclusterfactory const*>, boost::_bi::value<char*>, boost::reference_wrapper<std::vector<std::tr1::shared_ptr<danapi::storagecluster const>, std::allocator<std::tr1::shared_ptr<danapi::storagecluster const> > > >, boost::reference_wrapper<std::tr1::shared_ptr<danapi::storagecluster const> >, boost::reference_wrapper<boost::exception_ptr> > >::operator() (this=0x896740) @ /usr/include/boost/bind/bind_template.hpp:20 #8 0x00007fffef3a19cc in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::cmf4<void, danapi::storageclusterfactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danapi::conststorageclusterptrlist const&, danapi::conststorageclusterptr&, boost::exception_ptr&>, boost::_bi::list5<boost::_bi::value<danapi::storageclusterfactory const*>, boost::_bi::value<char*>, boost::reference_wrapper<std::vector<std::tr1::shared_ptr<danapi::storagecluster const>, std::allocator<std::tr1::shared_ptr<danapi::storagecluster const> > > >, boost::reference_wrapper<std::tr1::shared_ptr<danapi::storagecluster const> >, boost::reference_wrapper<boost::exception_ptr> > > >::run (this=0x896610) @ /usr/include/boost/thread/detail/thread.hpp:56 #9 0x00007fffed8c2d97 in thread_proxy () /usr/lib64/libboost_thread-mt.so.5 #10 0x000000337a007851 in start_thread () /lib64/libpthread.so.0 #11 0x00000033794e811d in clone () /lib64/libc.so.6 then should have gotten 2 more setcontrollerclock() before:
#0 0x000000337c8bccb0 in __cxa_throw () /usr/lib64/libstdc++.so.6 #1 0x00007ffff143fc4c in swig::swigpyiteratorclosed_t<__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<danapi::controller>*, std::vector<std::tr1::shared_ptr<danapi::controller>, std::allocator<std::tr1::shared_ptr<danapi::controller> > > >, std::tr1::shared_ptr<danapi::controller>, swig::from_oper<std::tr1::shared_ptr<danapi::controller> > >::value (this=0x87bf50) @ /home/chchr/src/hpsphal/build/python/hpsphalpython_wrap.cxx:4894 #2 0x00007ffff101ddb7 in swig::swigpyiterator::next (this=0x87bf50) @ /home/chchr/src/hpsphal/build/python/hpsphalpython_wrap.cxx:3472 #3 0x00007ffff07a083c in _wrap_swigpyiterator_next (args=0x7ffff7f69850) @ /home/chchr/src/hpsphal/build/python/hpsphalpython_wrap.cxx:14301 #4 0x000000337b8deb24 in pyeval_evalframeex () /usr/lib64/libpython2.6.so.1.0 #5 0x000000337b8e0797 in pyeval_evalcodeex () /usr/lib64/libpython2.6.so.1.0 #6 0x000000337b86edb0 in ?? () /usr/lib64/libpython2.6.so.1.0 #7 0x000000337b844303 in pyobject_call () /usr/lib64/libpython2.6.so.1.0 #8 0x000000337b85970f in ?? () /usr/lib64/libpython2.6.so.1.0 #9 0x000000337b844303 in pyobject_call () /usr/lib64/libpython2.6.so.1.0 #10 0x000000337b89d5eb in ?? () /usr/lib64/libpython2.6.so.1.0 #11 0x000000337b8da458 in pyeval_evalframeex () /usr/lib64/libpython2.6.so.1.0 #12 0x000000337b8e0797 in pyeval_evalcodeex () /usr/lib64/libpython2.6.so.1.0 #13 0x000000337b8e0872 in pyeval_evalcode () /usr/lib64/libpython2.6.so.1.0 #14 0x000000337b8fbbbc in ?? () /usr/lib64/libpython2.6.so.1.0 #15 0x000000337b8fbc90 in pyrun_fileexflags () /usr/lib64/libpython2.6.so.1.0 #16 0x000000337b8fd17c in pyrun_simplefileexflags () /usr/lib64/libpython2.6.so.1.0 #17 0x000000337b909c32 in py_main () /usr/lib64/libpython2.6.so.1.0 #18 0x000000337941ecdd in __libc_start_main () /lib64/libc.so.6 #19 0x0000000000400649 in _start () catch throw c++ program:
catchpoint 1 (exception thrown), 0x000000337c8bccb0 in __cxa_throw () /usr/lib64/libstdc++.so.6 (gdb) bt #0 0x000000337c8bccb0 in __cxa_throw () /usr/lib64/libstdc++.so.6 #1 0x00007ffff6e9610c in boost::throw_exception<danapi::exception> (e=...) @ /usr/include/boost/throw_exception.hpp:64 #2 0x00007ffff72a065f in danapi::controller_rcim::setclock (this=0x641430) @ /home/chchr/src/hpsphal/storage-lib/src/controller_rcim.cpp:2128 #3 0x00000000004072ac in main (argc=1, argv=0x7fffffffe728) @ /home/chchr/src/hpsphal/python/foo.cpp:39
in .i file, %exception block puts try around function, in each catch clause, prints error continues execution if there had been no exception. surely not intended, because result won't exceptions propagated python (how you? you've told swig generate code ignore them). use exception.i, explained in section 11.1.7 of swig manual. example,
%include exception.i %exception { try { $action } catch(const danapi::exception& e) { swig_exception(swig_valueerror, "dan api exception"); } catch(const std::exception& e) { swig_exception(swig_unknownerror, "standard exception"); } catch(const boost::exception& e) { swig_exception(swig_unknownerror, "boost exception"); } catch(...) { swig_exception(swig_runtimeerror, "unknown exception"); } } i've never looked @ code generated guess swig_exception causes flag set, swig checks after execution of $action, if set swig uses python api throw python exception.
update:
if never see error message , don't catch clause c++ library not throwing exception. issue not wrapper code (setcontrollerclock), own c++ library code setclock, or perhaps not calling in context raise exception. issue not related generated code, swig, or python. library.
to prove this: put throw std::runtime_error("test") after $action line. end in second catch clause, , e.what() "test":
%exception { try { $action throw std::runtime_error("test"); } catch(const danapi::exception& e) { swig_exception(swig_valueerror, "dan api exception"); } catch(const std::exception& e) { swig_exception(swig_unknownerror, "standard exception");
Comments
Post a Comment