diff --git a/base/channels.jl b/base/channels.jl index 33365c03e5d3d..1b5b427f92671 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -253,6 +253,7 @@ Stacktrace: """ function bind(c::Channel, task::Task) T = Task(() -> close_chnl_on_taskdone(task, c)) + T.sticky = false _wait2(task, T) return c end diff --git a/base/task.jl b/base/task.jl index e407cbd62bbd6..564f18d3b9d29 100644 --- a/base/task.jl +++ b/base/task.jl @@ -317,22 +317,22 @@ end # have `waiter` wait for `t` function _wait2(t::Task, waiter::Task) if !istaskdone(t) + # since _wait2 is similar to schedule, we should observe the sticky + # bit, even if we don't call `schedule` with early-return below + if waiter.sticky && Threads.threadid(waiter) == 0 && !GC.in_finalizer() + # Issue #41324 + # t.sticky && tid == 0 is a task that needs to be co-scheduled with + # the parent task. If the parent (current_task) is not sticky we must + # set it to be sticky. + # XXX: Ideally we would be able to unset this + current_task().sticky = true + tid = Threads.threadid() + ccall(:jl_set_task_tid, Cint, (Any, Cint), waiter, tid-1) + end lock(t.donenotify) if !istaskdone(t) push!(t.donenotify.waitq, waiter) unlock(t.donenotify) - # since _wait2 is similar to schedule, we should observe the sticky - # bit, even if we aren't calling `schedule` due to this early-return - if waiter.sticky && Threads.threadid(waiter) == 0 && !GC.in_finalizer() - # Issue #41324 - # t.sticky && tid == 0 is a task that needs to be co-scheduled with - # the parent task. If the parent (current_task) is not sticky we must - # set it to be sticky. - # XXX: Ideally we would be able to unset this - current_task().sticky = true - tid = Threads.threadid() - ccall(:jl_set_task_tid, Cint, (Any, Cint), waiter, tid-1) - end return nothing else unlock(t.donenotify)