Skip to content

Nasty hidden invariant in deschedule_running_task_and_then #8132

Closed
@bblum

Description

@bblum

There is currently a gentleperson's agreement about the use of the higher-order context switchers in the new runtime. Usually, they are to be used like this:

let mut environment = ...;
do sched.deschedule_running_task_and_then |sched, task| {
    ... use environment ...
    sched.schedule_blocked_task(task);
}
... use environment ...

However, because the closure ("cleanup job") runs in scheduler context, on SMP the task can resume on a different core before the closure finishes running. Hence, if you did:

let mut environment = ...;
do sched.deschedule_running_task_and_then |sched, task| {
    sched.schedule_blocked_task(task);
    ... use environment ... // A
}
... use environment ... // B

...then A and B will race and the world will explode.

There are two possible solutions. One is to leave this issue open forever, and audit all uses of the context-switchers before doing each major release. The second is to use the type system (which once again proves expressive enough to deal with this sort of thing). It would look something like this:

impl Scheduler {
    // Passes the environment explicitly as a noncopyable Env token.
    fn deschedule_running_task_and_then<E>(~self, E, extern fn(&mut Scheduler, BlockedTask, Env<E>))

    // Wakes a blocked task, also proving that the caller won't access its environment anymore.
    fn schedule_blocked_task<E>(&mut self, BlockedTask, Env<E>)
}
impl <E> Env<E> {
    // Can only access environment as long as opaque Env permission token is held.
    fn get<'a>(&'a mut self) -> &'a mut E
}

There is just one problem with this, which is that it doesn't save you if you're already manipulating unsafe pointers as part of the environment (such as we do in comm::PortOne). Those use sites will have to be audited nonetheless.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-concurrencyArea: ConcurrencyA-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflowsE-hardCall for participation: Hard difficulty. Experience needed to fix: A lot.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions