Skip to content

Commit

Permalink
Throw ConcurrencyViolationError on yield with current_task (#53974
Browse files Browse the repository at this point in the history
)

Previously, this errored with a nasty type assert *somewhere* in the
runtime. Throwing a proper `ConcurrencyViolationError` allows this to be
debugged, and makes the error condition better known.
  • Loading branch information
Seelengrab authored Apr 16, 2024
1 parent 824ceef commit d7a354a
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 3 deletions.
8 changes: 6 additions & 2 deletions base/task.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1050,11 +1050,15 @@ end
A fast, unfair-scheduling version of `schedule(t, arg); yield()` which
immediately yields to `t` before calling the scheduler.
Throws a `ConcurrencyViolationError` if `t` is the currently running task.
"""
function yield(t::Task, @nospecialize(x=nothing))
(t._state === task_state_runnable && t.queue === nothing) || error("yield: Task not runnable")
current = current_task()
t === current && throw(ConcurrencyViolationError("Cannot yield to currently running task!"))
(t._state === task_state_runnable && t.queue === nothing) || throw(ConcurrencyViolationError("yield: Task not runnable"))
t.result = x
enq_work(current_task())
enq_work(current)
set_next_task(t)
return try_yieldto(ensure_rescheduled)
end
Expand Down
4 changes: 3 additions & 1 deletion test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,12 @@ end

@test_throws ConcurrencyViolationError("deadlock detected: cannot wait on current task") wait(current_task())

@test_throws ConcurrencyViolationError("Cannot yield to currently running task!") yield(current_task())

# issue #41347
let t = @async 1
wait(t)
@test_throws ErrorException yield(t)
@test_throws ConcurrencyViolationError yield(t)
end

let t = @async error(42)
Expand Down

0 comments on commit d7a354a

Please sign in to comment.