Python callbacks & PyGILState_Release()

David E. Konerding DSD staff dek at bosshog.lbl.gov
Mon Apr 25 10:43:27 EDT 2005


In article <mailman.2345.1114265296.1799.python-list at python.org>, Randall Hopper wrote:
> Thomas Heller:
> |>      Python -> C++ -> Python Callback
> |>
> |> (example attached) an exception raised in the callback doesn't make it back
> |> across C++ to Python.
> ...
> |> void callback_wrapper( void *user_data )
> |> {
> |>   // Acquire interpreter lock
> |>   PyGILState_STATE gstate = PyGILState_Ensure();
> |>   ...
> |>   // Call Python
> |>   pyresult = PyEval_CallObject( pyfunc, pyargs );
> |>   ...
> |
> |    if (pyresult == NULL)
> |        PyErr_Print();
> |
> |>   // Free interpreter lock
> |>   PyGILState_Release(gstate);
> |> }
> |
> |PyErr_Print() will do the 'right' thing?s.
> 
> Thanks for the reply.  However, this won't:
> 
>    a) Stop the main Python script, and
>    b) Print the full stack trace (including Python and C++ SWIG wrapper)
> 
> Is there a clean way to save the full exception state in the callback
> before the PyGILState_Release(), and restore it when we return across the
> C++ wrapper?
> 
> If I knew what the proper "save" and "restore" exception state code bits
> were, I could easily implement this with exception typemaps in SWIG.
> 
> Thanks,
> 
> Randall
> 
> P.S. Perhaps PyGILState_Release should take an argument instructing it to
> exclude exception state when resetting the interpreter state back to its
> original state.

Randall:

It's not the job of the PyGILState_* functions to manage exception details for you.

I always solved this problem a different way, by saving the exception in an instance variable
within the Python callback, and using a condition variable so that the main thread could abort on a callback's
failure.  Notably, our callsbacks are always invoked from a C++ thread that the main Python interepreter didn't
create, and our main Python intepreter is blocked on a mutex most of the time.

I saved the exception state by retrieveing it from sys.exc_info(), which contains all the traceback object data as Python variable.
I think you can get the same info from your C++ callback wrapper, and use PyErr_Fetch and PyErr_Restore to save and restore the
exception sate.

Dave




More information about the Python-list mailing list