[Stackless] "Attempt to run a locked frame!"

Christian Tismer tismer at tismer.com
Tue Feb 20 14:54:24 CET 2001

Bernd Rinn wrote:
> On Tue, Feb 20, 2001 at 01:53:47PM +0100, Christian Tismer wrote:
> > [...] Ah, now I get some idea.
> > Is it possible to give me the traceback as well?
> > As Gordon explained nicely, someone is stepping on
> > forbidden traps. But since it appears that you
> > don't touch continuations directly, we might in fact
> > have a bug in the MT package.
> Yes, of coarse. Here is the complete output from one run of
> miniserver.py with two clients connnected:
> ~/projekte/prpc/debug_uthread/miniserver $ python miniserver.py
> serverloop()
> serverloop()
> serverloop()
> handle()
> received: (1, 2)
> handle()
> received: (1, 2)
> Traceback (most recent call last):
>   File "uthread.py", line 1156, in makeTask
>     apply(func, args, kw)
>   File "miniserver.py", line 13, in handle
>     timeout=timeout)
> SystemError: Attempt to run a locked frame!

Ok, maybe I've got it.
In miniserver.py, you are doing the following:

class socketFile:
    def __init__(self, sock, mode, init_buffer="", timeout=10):
        self.socket  = sock
        self.buffer  = init_buffer
        self.mode    = mode
        self.timeout = timeout
        if mode == readMode: self.get()

Now, get() calls the wait function from the uthread package.
wait() appends your current thread to a waiting list and
schedules the next one. In the case of a single client,
the next thread is the same thread, it just continues
and everything is fine.        

Problem: You are crreating a thread in the context of
an __xxx__ method, __init__ in this case. This is a
problem with Stackless, since these special methods
are still causing an interpreter recursion.

What happens is the following:
The first client tries to wait(), causing a recursion. So far
so good. Then your second client is started and does the
same. This interpreter is now nested into the other call, since
the other __init__ isn't yet gone.
At the second wait() call, the uthread package tries to
reschedule the first task, but the frame which is needed to run
is sitting in the other interpreter which is hidden by the
new one. That is forbidden, and prevented by continuationmodule.

I'm not sure whether to call this an error in uthread. If possible,
I'll try to check for this situation and give a better error
message. But from uthread's view, calling wait() from an interpreter
recursion is an abuse. It is Stackless' incompletenes that causes
this. Only normal function calls are stackless.

Solution for you, probably:
Don't call get in the __init__ method. Just remove it and add
a line to the caller.

def handle(req, addr, conns, timeout):
    print "handle()"
    while 1:
        f = socketFile.socketFile(req,
	f.get()  # this!

I hope this helps.
Making Stackless completely stackless is a very hard task
but will hapen at some time in the future.

cheers - chris

Christian Tismer             :^)   <mailto:tismer at tismer.com>
Mission Impossible 5oftware  :     Have a break! Take a ride on Python's
Kaunstr. 26                  :    *Starship* http://starship.python.net
14163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     where do you want to jump today?   http://www.stackless.com
Stackless mailing list
Stackless at starship.python.net

More information about the Stackless mailing list