[Stackless] curl makes stackless wsgi die :(

Richard Tew richard.m.tew at gmail.com
Tue Feb 3 14:44:48 CET 2009


On Mon, Feb 2, 2009 at 4:05 AM,  <jtunney at lobstertech.com> wrote:
> I wrote a small program that runs a simple WSGI server but it is silently
> dying after receiving a request from curl.  I used the stacklesswsgi.py
> module below and tested on both stackless 2.6.1 and 2.5.2 (Mac OS)  You can
> reproduce this easily with the following code:

Well, I don't have this curl thingy so can't reproduce this.  But I
will witter on about it some.

> The request is handled properly, and then the server dies, stackless.run()
> exits, and the program silently dies.  It seems the tasklet acting as the
> listening server dies when entering "self.accept_channel.receive()"
> (stacklesswsgi.py:171)  and receive() never returns.  receive doesn't raise
> an exception nor will it execute code wrapped into a 'finally' block.  I'm
> very new to stackless so I want to refrain from making too assumptions, but
> a 'finally' block not being executed might indicate a bug in the
> interpreter.
>
> Also the asyncore tasklet continues running even after the server tasklet
> dies.

Unfortunately, your description is ambiguous.

stackless.run() will exit when there are no runnable tasklets.  In
order for it to exit, either all runnable tasklets have to have exited
or have been blocked outside the scheduler.

If I had to cast a guess at what is going on here, I would assume that
all the tasklets created by the Stackless WSGI file are blocked on
channels leaving the scheduler empty.

You could examine this claim by doing the following in the Stackless
WSGI file in the appropriate places...

Making a weakref to each tasklet created and storing them somewhere accessible.

t = self.tasklet_class(self._accept_loop)()
self.acceptTasklet = weakref.proxy(t)

t = stackless.tasklet(asyncore_loop)()
self.asyncoreTasklet = weakref.proxy(t)

t = self.tasklet_class(comm)(conn)
if not hasattr(self, "connectionTasklets"):
    self.connectionTasklets = weakref.WeakValueDictionary()
self.connectionTasklets[addr] = t

When the server exits, looking at these weakrefs, seeing if they are
still valid, and if they are, whether they are blocked on channels.

if __name__ == '__main__':
   import stacklesswsgi
   s = stacklesswsgi.Server(('127.0.0.1', 8080), wsgi_app)
   s.start()
   print "scheduler exited, looking at known tasklet state"
   def CheckTasklet(text, taskletWeakref):
       try:
           onChannel = not taskletWeakref._channel
           print text, "= on channel =", onChannel
       except ReferenceError:
           print text, "= dead"
   CheckTasklet("Accept tasklet", s.acceptTasklet)
   for k, v in s.connectionTasklets.itervalues():
       CheckTasklet("Connection tasklet "+ str(k), v)
   CheckTasklet("Asyncore dispatcher tasklet", sock_server.asyncoreTasklet)

I would assume that this is a bug in the WSGI code rather than
Stackless.  But please, if you have the time to try this, let us know
what the result is.

Cheers,
Richard.




More information about the Stackless mailing list