Skip to content

Commit 7cf01e5

Browse files
authoredMay 6, 2023
Merge pull request #49601 from JuliaLang/kp/channel-task-fix
Reduce unnecessary task stickiness from Channel bind calls. Fix also a race condition between scheduling a Task and picking which thread it is sticky to.
2 parents 633d1ae + 9dbfc05 commit 7cf01e5

File tree

2 files changed

+13
-12
lines changed

2 files changed

+13
-12
lines changed
 

‎base/channels.jl‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ Stacktrace:
253253
"""
254254
function bind(c::Channel, task::Task)
255255
T = Task(() -> close_chnl_on_taskdone(task, c))
256+
T.sticky = false
256257
_wait2(task, T)
257258
return c
258259
end

‎base/task.jl‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -318,22 +318,22 @@ end
318318
# have `waiter` wait for `t`
319319
function _wait2(t::Task, waiter::Task)
320320
if !istaskdone(t)
321+
# since _wait2 is similar to schedule, we should observe the sticky
322+
# bit, even if we don't call `schedule` with early-return below
323+
if waiter.sticky && Threads.threadid(waiter) == 0 && !GC.in_finalizer()
324+
# Issue #41324
325+
# t.sticky && tid == 0 is a task that needs to be co-scheduled with
326+
# the parent task. If the parent (current_task) is not sticky we must
327+
# set it to be sticky.
328+
# XXX: Ideally we would be able to unset this
329+
current_task().sticky = true
330+
tid = Threads.threadid()
331+
ccall(:jl_set_task_tid, Cint, (Any, Cint), waiter, tid-1)
332+
end
321333
lock(t.donenotify)
322334
if !istaskdone(t)
323335
push!(t.donenotify.waitq, waiter)
324336
unlock(t.donenotify)
325-
# since _wait2 is similar to schedule, we should observe the sticky
326-
# bit, even if we aren't calling `schedule` due to this early-return
327-
if waiter.sticky && Threads.threadid(waiter) == 0 && !GC.in_finalizer()
328-
# Issue #41324
329-
# t.sticky && tid == 0 is a task that needs to be co-scheduled with
330-
# the parent task. If the parent (current_task) is not sticky we must
331-
# set it to be sticky.
332-
# XXX: Ideally we would be able to unset this
333-
current_task().sticky = true
334-
tid = Threads.threadid()
335-
ccall(:jl_set_task_tid, Cint, (Any, Cint), waiter, tid-1)
336-
end
337337
return nothing
338338
else
339339
unlock(t.donenotify)

0 commit comments

Comments
 (0)
Please sign in to comment.