[Stackless] Stackless runtime smacking into GIL while a callback is running

Adam Preble adam.preble at gmail.com
Sun Mar 11 20:28:32 CET 2012


I've been writing a C++ application with an embedded Python interpreter,
for which I am using Stackless Python 2.6.5.  I am using Boost to wrap my
objects.  I had the great fortune of running head-first into the GIL when I
started calling back into Python objects that were implementing some C++
interfaces.  These calls are coming in from a variety of threads in the C++
runtime, and the rest was history.

Hence, I am no stranger to our friend "PyThreadState_Get: no current
thread." I've learned how to acquire the GIL in my wrappers and there was
peace in the land again.

The problem this time is my call stack takes me right to the thread with
the Stackless Python runtime in it, and not some imposter thread.  I see
the runtime itself trying to secure the thread state, and there I hit the
error.

In my Python code, I have this main thread running a horrific poll loop:

        # Busy loop while waiting for escape key
        while not self.stopLoop:
            stackless.schedule()

Indeed this is a terrible way to do it, but it's a stop gap while I bring
up a lot of other code.  I am pretty sure if I improved on this with
condition variables or monitors or whatever Stackless uses, that I would
still have the problem--I may yet try this while waiting for some hints
just to reduce the amount of bile I imagine that code is generating.

The callback looks like this:
    def ReceiveInputEvent(self, inputType, eventData):
        print "Received input event"
        if inputType == CECControlTypes.QuitProgram:
            print "Setting stopLoop = True"
            self.stopLoop = True

Right now when I hit escape, it will come back multiple times so long as I
have held it down.  That wasn't my goal, and I want to work on that, but it
makes the problem much more chronic at the moment so I'm keeping it.  It'll
crash sometimes in the middle of this code, and sometimes after I have
cleared it.  The wrapper is doing this:

PyGILState_STATE gstate = PyGILState_Ensure();
this->get_override("ReceiveInputEvent")(type, eventData);
PyGILState_Release(gstate);

This code is behaving for me; the Ensure call succeeds and I don't see
issues with the release.  Maybe I'm not checking for them?  I have set
breakpoints at the Ensure and Release and I see the error can also happen
once I am clear of the Release.

One thing is for certain--if I don't ever trigger that callback, everything
is fine, or at least I don't get that error.

I'm assuming that somehow Stackless didn't get the memo that I stole the
interpreter for a moment for another thread.  Is there some special rules I
need to honor with it when I do this crazy stuff?

Environment:]
I'm using Boost 1.47
My OS is Vista 64-bit
I'm using Visual Studio 2010
I'm building and running with debug symbols on, including Python.

Stackless Python startup string:
Python 2.6.5 Stackless 3.1b3 060516 (release26-maint, Feb 15 2012,
09:11:40) [MSC v.1600 32 bit (Intel)] on win32

I am using a 2.6 one since it mates up with Boost well.  If we have good
reason to move on to a newer one, I have to see what mates with Boost now
and try to work with that.  But let's say trying a new version of Stackless
is nontrivial.  I'm also assuming I just missed something and all would be
well.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.stackless.com/pipermail/stackless/attachments/20120311/ef3ecf59/attachment.html>


More information about the Stackless mailing list