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

Bernd Rinn Bernd.Rinn at epost.de
Tue Feb 20 13:04:50 CET 2001

On Mon, Feb 19, 2001 at 07:55:23PM -0500, Gordon McMillan wrote:
> [...] What's probably going on is either (1) trying to use a 
> continuation from a recursive invocation of Python or (2) trying 
> to use a plain callable object as a continuation.
> You could hit (1), for example, by trying to use a continuation 
> within a __getitem__ (or other magic method). This is 
> implemented by C code that realizes it needs to execute pure 
> Python, so recursively invokes the interpreter. But if that pure 
> Python tries to use a continuation created in an outer 
> invocation of the interpreter, it would trash the C stack. So, it's 
> streng verbotten. [...]

Does "use a continuation" include an automatic task switch performed
by the uthread module? And as a consequence: are magic methods written
in Python generally a bad idea when using microthreads? I do not use
continuations directly but only the uthread module. What actions in
uthreaded programs could trigger (1) or (2)?

More generally: Is there somewhere a list of do's and dont's when
using microthreads? 

I have written a metathread package to encapsulate differences between
threads und uthreads and a multithreaded server framework that makes
use of it (python remote procedure calls) and I want to make it freely
available to the Python community very soon. It has been a nice amount
of work and I really want to get it out of the door. Unfortunately the
"Attempt to run a locked frame!" exception crashes each and any
prpc-session when using microthreads instead of Python threads.

> BTW, your sample code neglected to say what module was 
> what, so I didn't bother to try it.

Oh, I am sorry about that. So here are the explanations:

* comm.py contains functions to perform socket operations in a
  non-blocking way (when using microthreads), such as accept() or
  send(). The core function of this module is nbselect() which
  substitutes select.select() from the Python Libarary. So if 's' is a
  socket you do not call 
  but instead 
    comm.send(s, buffer)
  (BTW: the nbselect() in connect() is rubbish.)

* socketFile.py defines a class socketFile that is instantiated with a
  socket 'sock' and a mode (either readMode or writeMode). It is used
  to transmit Python data objects over a socket by means of pickling
  and unpickling. To transmit an object 'x', you do:

  f = socketFile.socketFile(sock, socketFile.writeMode)
  cPickle.dump(x, f)

  f = socketFile.socketFile(sock, socketFile.readMode)
  x = cPickle.load(f)

* miniserver.py spawns a uthreaded server that is listening on 'PORT'
  (which is set to 50000). It consists of (1) serverloop() which
  accept()s new connections and (2) handle() which handles the connection
  requests. serverloop() spawns a new microthread for each
  connection running the function handle() therein.

* miniclient.py makes a connection to port 'PORT' on localhost and
  causes some network traffic in a loop. It transmits trash to the
  server and receives a list of active connections. Finally it sends
  a 'None' to finish the connection.

When I start one miniserver and one miniclient everything works
well. As soon as I start two miniclients in parallel, the server
bombs with the exception

SystemError: Attempt to run a locked frame!

Since I am not familiar with continuations I see no way to track down
that bug myself. I ask myself, if it bites other uthread users as well...


Bernd Rinn
Fakultät für Physik
Universität Konstanz

Tel. 07531/88-3812, 
e-mail: Bernd.Rinn at uni-konstanz.de
PGP-Fingerprint: 1F AC 31 64 FF EF A9 67  6E 0D 4C 26 0B E7 ED 5C
Stackless mailing list
Stackless at starship.python.net

More information about the Stackless mailing list