Skip to content

Commit d49c6f2

Browse files
JeffBezansonKristofferC
authored andcommitted
fix #41347, better checks for yield and yieldto with finished tasks (#41410)
(cherry picked from commit e2d5f52)
1 parent fd2d0c9 commit d49c6f2

File tree

3 files changed

+21
-6
lines changed

3 files changed

+21
-6
lines changed

base/task.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ A fast, unfair-scheduling version of `schedule(t, arg); yield()` which
721721
immediately yields to `t` before calling the scheduler.
722722
"""
723723
function yield(t::Task, @nospecialize(x=nothing))
724+
(t._state === task_state_runnable && t.queue === nothing) || error("yield: Task not runnable")
724725
t.result = x
725726
enq_work(current_task())
726727
set_next_task(t)
@@ -736,6 +737,13 @@ call to `yieldto`. This is a low-level call that only switches tasks, not consid
736737
or scheduling in any way. Its use is discouraged.
737738
"""
738739
function yieldto(t::Task, @nospecialize(x=nothing))
740+
# TODO: these are legacy behaviors; these should perhaps be a scheduler
741+
# state error instead.
742+
if t._state === task_state_done
743+
return x
744+
elseif t._state === task_state_failed
745+
throw(t.result)
746+
end
739747
t.result = x
740748
set_next_task(t)
741749
return try_yieldto(identity)

src/task.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,8 @@ JL_DLLEXPORT void jl_switch(void)
475475
if (t == ct) {
476476
return;
477477
}
478-
if (t->_state != JL_TASK_STATE_RUNNABLE || (t->started && t->stkbuf == NULL)) {
479-
ct->_isexception = t->_isexception;
480-
ct->result = t->result;
481-
jl_gc_wb(ct, ct->result);
482-
return;
483-
}
478+
if (t->started && t->stkbuf == NULL)
479+
jl_error("attempt to switch to exited task");
484480
if (ptls->in_finalizer)
485481
jl_error("task switch not allowed from inside gc finalizer");
486482
if (ptls->in_pure_callback)

test/misc.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,17 @@ end
182182

183183
@test_throws ErrorException("deadlock detected: cannot wait on current task") wait(current_task())
184184

185+
# issue #41347
186+
let t = @async 1
187+
wait(t)
188+
@test_throws ErrorException yield(t)
189+
end
190+
191+
let t = @async error(42)
192+
Base._wait(t)
193+
@test_throws ErrorException("42") yieldto(t)
194+
end
195+
185196
# test that @sync is lexical (PR #27164)
186197

187198
const x27164 = Ref(0)

0 commit comments

Comments
 (0)