[Stackless] why the TaskletExit?

Andrew Dalke dalke at dalkescientific.com
Wed Jan 24 21:18:06 CET 2007


On Jan 24, 2007, at 5:37 PM, Jeff Senn wrote:
> Perhaps run.__doc__ which says:
>
>    run_watchdog(timeout) -- run tasklets until they are all done, or
> timeout instructions have passed. ...
>
> Should say this instead:
>
>    run_watchdog(timeout) -- run tasklets until they are all done OR
> BLOCKED, ...

That still doesn't describe the behavior I see, which is that
a receive raises a TaskExit exception.

Hmm, perhaps it's part of the garbage collection?  Yeah,
that's it.  Here's modified code which keeps the reference.
Comment/un-comment the "del t" to see the exception thrown
in the receive.

import stackless

def counter(chan, start, end):
     print "Starting counter"
     while start < end:
         print "Sending value", start
         chan.send(start)
         start = start + 1
     print "Counter finished"


def main():
     chan = stackless.channel()
     # Start a new tasket and put it on the end of the task queue
     stackless.tasklet(counter)(chan, 0, 4)
     print "Created new tasklet"

     while 1:
         # Read from the channel.  If the channel is empty this
         # yields control to another tasklett
         try:
             val = chan.receive()
         except:
             print "Got the exception"
             raise
         print "Received", val

if __name__ == "__main__":
     t = stackless.tasklet(main)
     t()
     stackless.run()
     # comment this out to see different behavior
     del t
     print "This is the end"


> If you get into a (detectable) deadlock (as in this case where there
> is simply nothing to run) then .run() will return.

And perhaps it looses a ref count?  I still haven't figured
out that one.  I need to examine who knows about whom.

It's in scheduling.c with tasklet_end, and there's the
"check_for_deadlock" test, and .. well, more code that
sounds right but which I don't quite follow.


> It has to work this way because there is no place to take up the CPU
> time spinning and waiting for nothing.

I understood that.  I was trying to figure out how it got
to the point where it raise the code.  Was it the "run()"
or the "schedule()" or something else?  In this case it
was (I think) the finalization code in taskletobject.c:


static TASKLET_KILL_HEAD(impl_tasklet_kill)
  ...
         /* we might be called after exceptions are gone */
         if (PyExc_TaskletExit == NULL) {
                 PyExc_TaskletExit = PyString_FromString("zombie");
                 if (PyExc_TaskletExit == NULL)
                         return NULL; /* give up */
         }
         noargs = PyTuple_New(0);
         STACKLESS_PROMOTE_ALL();
         ret = impl_tasklet_raise_exception(task, PyExc_TaskletExit,
                                            noargs);



> I'm not sure what you mean by (other than to guess that "exist"
> should be "exit"....):
>
>>   From experimentation it looks like if there's no way for
>> a tasklet to send anything then all tasklets blocked on a
>> receive are told to exist.  That's guesswork and I would like
>> clarification on the behavior.
>
> Are you asking for some sort of 
> send-a-message-that-destroys-the-channel
> (and anyone waiting on it) feature?

That didn't make sense, did it.  Looking at it now I don't
even know what I was thinking.  But I do know now what I
wanted, which is that the behavior comes from gc.


					Andrew
					dalke at dalkescientific.com


_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless



More information about the Stackless mailing list