Skip to content

Commit

Permalink
Throw ConcurrencyViolationError on yield & throwto with `curren…
Browse files Browse the repository at this point in the history
…t_task`

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 known.
  • Loading branch information
Seelengrab committed Apr 6, 2024
1 parent d963a34 commit c37ee02
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
10 changes: 8 additions & 2 deletions base/task.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1040,11 +1040,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) || error("yield: Task not runnable $t")
t.result = x
enq_work(current_task())
enq_work(current)
set_next_task(t)
return try_yieldto(ensure_rescheduled)
end
Expand Down Expand Up @@ -1091,6 +1095,8 @@ end

# yield to a task, throwing an exception in it
function throwto(t::Task, @nospecialize exc)
current = current_task()
t === current && throw(ConcurrencyViolationError("Cannot throw an exception to the currently running task!"))
t.result = exc
t._isexception = true
set_next_task(t)
Expand Down
3 changes: 3 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ end

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

@test_throws ConcurrencyViolationError("Cannot yield to currently running task!") yield(current_task())
@test_throws ConcurrencyViolationError("Cannot throw an exception to the currently running task!") throwto(current_task(), ArgumentError())

# issue #41347
let t = @async 1
wait(t)
Expand Down

0 comments on commit c37ee02

Please sign in to comment.