[Stackless] unexpected tasklet & channel behaviour

Richard Tew richard.m.tew at gmail.com
Wed Nov 1 11:01:19 CET 2006

On 11/1/06, ardatur at mail.ru <ardatur at mail.ru> wrote:
> Wednesday, November 1, 2006, 10:35:59 AM, you wrote:
> RT> The only reference to the channel is inline, and when it
> RT> garbage collected...
> Interesting point, I haven't thought about gc... But actually the same
> result is obtained with `gc.disable()'. And anyway, if the reason were
> in gc, we should have seen `1 b', `2 b', ..., `5 b' lines in the output,
> right?

No.  There is a logic to this behaviour.

It is a combination of what is on the tasklet chain after a given tasklet
when you call run on it, and how you have used the channel in that

t1 = tasklet...
# t1 on tasklet chain.
# t1 removed from the tasklet chain.
t2 = tasklet...
# t2 on tasklet chain.
# t2 removed from the tasklet chain.

t1 = tasklet...
# t1 on tasklet chain.
t2 = tasklet...
# t1, t2 on tasklet chain.
# t1 runs. Blocks and is removed from the tasklet chain.
# t2 runs. Blocks and is removed from the tasklet chain.
# Now.. what happens on whether the channel in t2 is still
# around.  If it is, like in f2, then the tasklet will be blocked
# on the channel.  If it is now, like in f1, then the tasklet
# will not be blocked and will be as if it yielded in some
# manner.

> RT> Because f2 holds a local reference to the channel, the
> RT> tasklets on it do not get unblocked and any attempt to
> RT> manually run them fails, as it should.
> While receive() in f1 executes, doesn't something hold a reference
> to the respective channel, too?

The interpreter internals, but only for executing that expression.  But
what if the blocking on the receive is soft switching?  That receive
is effectively finished and the tasklet is blocked only waiting for
something to send it a return value, but the stack unwinds and all
now unused objects like the channel are freed as nothing really holds
a reference to them.

That this is a little unexpected is of course strange, but if no-one uses
channels like this really anyway! :-)

Christian could probably explain this a lot clearer, I just have the
experience of debugging how this works in order to fix crash bugs
and not so great an understanding of the precise workings of the

> >> 2) looks like `t1.run()' in the case 4 runs both t1 and t2, which
> >> results in a `t2.run()' failure.
> RT> Yes.  This is something that confused me too.  Doing tasklet.run
> RT> does not just run that tasklet.  It runs that tasklet and then all the
> RT> other scheduled tasklets after it the chain are run next, then it
> RT> exits.
> RT> No real bugs here.  Just unexpected ways things work :)
> OK, so tasklets are `already started, but not yet' even before run(),
> and this call only removes the `not yet' part, after which the
> scheduler kicks in and executes all tasklets, including those which
> are still in a `not yet' state. Unexpected, yeah :) .
> Well, that's one half of a problem. The other half is still about the
> `6 b' line. I guess I should've asked more detailed questions:
> * why `6 b' but not `5 b'? These two tasklets are the same func in
> different microthreads, shouldn't they be either both finished or both
> not?

Addressed above.  I kind of assumed you would interpolate that
from the two points, that the channel is garbage collected and how
you run the tasklets.  But of course I did not include enough

> * the `6 a' line is (like in case 4) output after `t1.run()', not
> `t2.run()'; and the `6 b' is reported after `t2.run()'. In the case 4
> the same call spawned an exception---in the case 3 the receive()
> simply returns None. Isn't it an inconsistency?

Not at all.  This is explained above.  The exception is correct
and the other cases inconsistency is a perfectly valid behaviour
taking into account that the channel may be, and is garbage
collected and what happens to the tasklets on it, when that

I hope this clears up the remaining confusion,

Stackless mailing list
Stackless at stackless.com

More information about the Stackless mailing list