PyThreadState_SetAsyncExc ignores except: clause

Bob Alistar bobalistar at
Thu Dec 4 11:34:21 CET 2003


I have an IVR server controlling Dialogic hardware through
a DLL exposing the C API to Python.  The server farms out
incoming calls to python scripts based on the telephone
number that was dialled, and these scripts are written by
other people, sometimes in other companies, and quite often
these people have no idea that a hangup event is actually
quite hard to catch in the middle of a while1:pass. I had
all sorts of alive/dead variables.  I had the server load
the code and pepper it with checks before I let it run.
Nothing worked for all cases, and 3 oclock mornings started
to get old (I use a live box, we have no test hardware ($$$)).

Now I ask single threads to store their thread_id, and
call PyThreadState_SetAsyncExc from my event loop.  It
works very well.  The only issue (aside from the fact
that I should not be using this at all ever ever ever
and that it was only put there for real developers),
is that the exception that is sent upwards from the C
call is not trapped (most?all?) of the time.  I think
it's because I'm doing some braindead stuff, so I beg
someone to look at this for me....

the C function I use
static PyObject * cvoice_async_exc(PyObject *self, PyObject *args) {
    PyObject *exc;
    int id, n;
    if (!PyArg_ParseTuple(args, "iO:async_exc", &id, &exc)) return NULL;
    n = PyThreadState_SetAsyncExc(id, exc);
    if (n > 1) {
        PyThreadState_SetAsyncExc(id, NULL);
        PyErr_SetString(ErrorObject,"Problem in async_exc: abort");
        return NULL;
    return Py_None;

and HangupError is defined like this:
class HangupError(Exception):
    def __init__(self, msg=''):
        self._msg = msg
        Exception.__init__(self, msg)

so from Python I do this
dll.async_exc(s.thread_id, HangupError)

while the thread is doing this
500: try:
501:     print "hello"
502: except HangupError:
503:     pass

and I get an exception message (caught from an outer "except Exception,msg:")
that reads like this:

Traceback (most recent call last):
  file, line 501, in run
        print "hello"

it was not caught?

I've quarter-solved the issue by doing this:

    f = cStringIO.StringIO()
    if f.getvalue().splitlines()[-1] == "HangupError": print "Caught"

any ideas or answers welcome.


More information about the Python-list mailing list