Huh, so I can cancel awaited future but I can’t cancel awaited group? (I am not sure if you meant Future by the “task”, but canceling awaited future works fine) That seems awkward. If that is really expected behavior I feel like that should be documented in Group.await and Group.cancel
Also yes, that await is supposed to “deadlock” until the cancel.
EDIT: I was wrong. canceling awaited Future also causes panic. I guess I will have to abuse conditions or something to achieve what I want…
In fact it’s allowed to do so, both await and cancel are idempotent, this allows for defer g.cancel(io) pattern to be used. The thing is that they’re not threadsafe, which is why it didn’t work in your case.
Well that is strange - I have also been getting the panic with zio (evented Io) when both await and cancel were running on the same thread. So it would seem the thread safety is not the issue (unless there was different reason for the panic with zio - but the stack trace looked about the same)
Yea this shouldn’t happen, unless you were copying the Io.Group itself? You can look at the implementation of Group.cancel and Group.await that is above the vtable, it checks if token is there, and only then calls to implementation.
I’m surprised about the panic in zio, but the general problem is, calling cancel or await inside the group is a deadlock. The operation has to wait until the group dies, but it can’t it you are blocking one task on await/cancel.
Okay, now that I am looking at it the stack trace doesn’t look same at all (I guess I just assumed that somehow because both panics were in the the std)…
The deadlock should not happen, since I am awaiting the group inside the group, which in my opinion should just make it wait until group.cancel is called (outside of the group) and then return error.Canceled - EDIT: Or so I believed, but I confirmed that awaiting group within the group indeed deadlocks at this branch - the other branch does not actually await within group but still crashes
Ok, now I see, this is essentially the same problem, just different semantics of the check. Zio uses the token as pointer to the task list, and it pops all tasks at the beginning of cancel. So when you hit the await, the token is already null and so it panics inside std.Io.Group.
Really, you can only safely await or cancel the group from the thread where you initiated it. Anything else will lead to problems. These checks are just avoiding the deadlock.
Sorry, I meant thread in the abstract concept, as in “thread of execution”. You always need to have one task owning the group, and only that one is doing either cancel or await. If you need synchronization from within the group, use event/condition/queue.