From 393f698a6cc5bfcfe3d05dedb8c55964bea3e162 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 14 Mar 2026 14:54:56 +0100 Subject: [PATCH 1/5] release-1.13: set VERSION to 1.13.0-beta3 (#61317) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b22da874e8150..9135fed9734a3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.13.0-beta2 +1.13.0-beta3 From aabfe948be4e311177382669bf24be838eecaa33 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 18 Feb 2026 13:44:46 +0100 Subject: [PATCH 2/5] Revert "make sched_task more robust (#59669)" This reverts commit 99dddb34ae4b15796684a974188dd2fcdd341e71. --- base/task.jl | 21 ++------------------- contrib/juliac/juliac-trim-base.jl | 1 - 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/base/task.jl b/base/task.jl index 9841bd947fdee..ae82fd8163e73 100644 --- a/base/task.jl +++ b/base/task.jl @@ -1161,25 +1161,9 @@ function throwto(t::Task, @nospecialize exc) return try_yieldto(identity) end -function wait_forever() +@inline function wait_forever() while true - try - while true - wait() - end - catch e - local errs = stderr - # try to display the failure atomically - errio = IOContext(PipeBuffer(), errs::IO) - emphasize(errio, "Internal Task ") - display_error(errio, current_exceptions()) - write(errs, errio) - # victimize another random Task also - if Threads.threadid() == 1 && isa(e, InterruptException) && isempty(Workqueue) - backend = repl_backend_task() - backend isa Task && throwto(backend, e) - end - end + wait() end end @@ -1240,7 +1224,6 @@ function wait() # thread sleep logic. sched_task = get_sched_task() if ct !== sched_task - istaskdone(sched_task) && (sched_task = @task wait()) return yieldto(sched_task) end task = ccall(:jl_task_get_next, Ref{Task}, (Any, Any, Any), trypoptask, W, checktaskempty) diff --git a/contrib/juliac/juliac-trim-base.jl b/contrib/juliac/juliac-trim-base.jl index fce275551751e..baa3d4825b971 100644 --- a/contrib/juliac/juliac-trim-base.jl +++ b/contrib/juliac/juliac-trim-base.jl @@ -12,7 +12,6 @@ end depwarn(msg, funcsym; force::Bool=false) = nothing _assert_tostring(msg) = "" reinit_stdio() = nothing - wait_forever() = while true; wait(); end JuliaSyntax.enable_in_core!() = nothing init_active_project() = ACTIVE_PROJECT[] = nothing set_active_project(projfile::Union{AbstractString,Nothing}) = ACTIVE_PROJECT[] = projfile From cd8c9ef58dbc4e2a4dc4ba10a9af53ea1badb16a Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 18 Feb 2026 13:25:53 +0100 Subject: [PATCH 3/5] Revert "simplify `wait()` (#58595)" This reverts commit 905a44b8ef49cc7f5e59e7ee65b0a71877aa8f58. --- base/task.jl | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/base/task.jl b/base/task.jl index ae82fd8163e73..324415678e92f 100644 --- a/base/task.jl +++ b/base/task.jl @@ -1217,19 +1217,30 @@ function wait() process_events() # get the next task to run + result = nothing + have_result = false W = workqueue_for(Threads.threadid()) task = trypoptask(W) - if task === nothing + if !(task isa Task) # No tasks to run; switch to the scheduler task to run the # thread sleep logic. sched_task = get_sched_task() if ct !== sched_task - return yieldto(sched_task) + result = yieldto(sched_task) + have_result = true + else + task = ccall(:jl_task_get_next, Ref{Task}, (Any, Any, Any), + trypoptask, W, checktaskempty) end - task = ccall(:jl_task_get_next, Ref{Task}, (Any, Any, Any), trypoptask, W, checktaskempty) end - set_next_task(task) - return try_yieldto(ensure_rescheduled) + # We may have already switched tasks (via the scheduler task), so + # only switch if we haven't. + if !have_result + @assert task isa Task + set_next_task(task) + result = try_yieldto(ensure_rescheduled) + end + return result end if Sys.iswindows() From 0ea99be7addc1b23dd81441d625214d4b23332e1 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 18 Feb 2026 13:27:55 +0100 Subject: [PATCH 4/5] Revert "Scheduler: Use a "scheduler" task for thread sleep (#57544)" This reverts commit 0d4d6d927d531c82e454e5a08c4bf6802cf69001. --- base/task.jl | 50 ++++++++-------------------- contrib/juliac/juliac-buildscript.jl | 1 - stdlib/Sockets/test/runtests.jl | 4 ++- test/channels.jl | 5 +-- 4 files changed, 19 insertions(+), 41 deletions(-) diff --git a/base/task.jl b/base/task.jl index 324415678e92f..8e7ac3fc53ceb 100644 --- a/base/task.jl +++ b/base/task.jl @@ -1161,16 +1161,6 @@ function throwto(t::Task, @nospecialize exc) return try_yieldto(identity) end -@inline function wait_forever() - while true - wait() - end -end - -const get_sched_task = OncePerThread{Task}() do - Task(wait_forever) -end - function ensure_rescheduled(othertask::Task) ct = current_task() W = workqueue_for(Threads.threadid()) @@ -1207,39 +1197,25 @@ end checktaskempty = Partr.multiq_check_empty +@noinline function poptask(W::StickyWorkqueue) + task = trypoptask(W) + if !(task isa Task) + task = ccall(:jl_task_get_next, Ref{Task}, (Any, Any, Any), trypoptask, W, checktaskempty) + end + set_next_task(task) + nothing +end + function wait() ct = current_task() # [task] user_time -yield-or-done-> wait_time record_running_time!(ct) - # let GC run GC.safepoint() - # check for libuv events - process_events() - - # get the next task to run - result = nothing - have_result = false W = workqueue_for(Threads.threadid()) - task = trypoptask(W) - if !(task isa Task) - # No tasks to run; switch to the scheduler task to run the - # thread sleep logic. - sched_task = get_sched_task() - if ct !== sched_task - result = yieldto(sched_task) - have_result = true - else - task = ccall(:jl_task_get_next, Ref{Task}, (Any, Any, Any), - trypoptask, W, checktaskempty) - end - end - # We may have already switched tasks (via the scheduler task), so - # only switch if we haven't. - if !have_result - @assert task isa Task - set_next_task(task) - result = try_yieldto(ensure_rescheduled) - end + poptask(W) + result = try_yieldto(ensure_rescheduled) + process_events() + # return when we come out of the queue return result end diff --git a/contrib/juliac/juliac-buildscript.jl b/contrib/juliac/juliac-buildscript.jl index 7fd46e58870f8..0b73f5a43b9d0 100644 --- a/contrib/juliac/juliac-buildscript.jl +++ b/contrib/juliac/juliac-buildscript.jl @@ -83,7 +83,6 @@ end #entrypoint(join, (Base.GenericIOBuffer{Memory{UInt8}}, Array{String, 1}, Char)) entrypoint(Base.task_done_hook, (Task,)) entrypoint(Base.wait, ()) -entrypoint(Base.wait_forever, ()) entrypoint(Base.trypoptask, (Base.StickyWorkqueue,)) entrypoint(Base.checktaskempty, ()) diff --git a/stdlib/Sockets/test/runtests.jl b/stdlib/Sockets/test/runtests.jl index 37921371b3bc5..00ffec12ffda4 100644 --- a/stdlib/Sockets/test/runtests.jl +++ b/stdlib/Sockets/test/runtests.jl @@ -556,12 +556,14 @@ end fetch(r) end - let addr = Sockets.InetAddr(ip"192.0.2.5", 4444) + let addr = Sockets.InetAddr(ip"127.0.0.1", 4444) + srv = listen(addr) s = Sockets.TCPSocket() Sockets.connect!(s, addr) r = @async close(s) @test_throws Base._UVError("connect", Base.UV_ECANCELED) Sockets.wait_connected(s) fetch(r) + close(srv) end end diff --git a/test/channels.jl b/test/channels.jl index 721eb478bd13a..f646b41cfa1a0 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -463,14 +463,15 @@ end cb = first(async.cond.waitq) @test isopen(async) ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) + ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) + @test isempty(Base.Workqueue) Base.process_events() # schedule event Sys.iswindows() && Base.process_events() # schedule event (windows?) + @test length(Base.Workqueue) == 1 ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) @test tc[] == 0 yield() # consume event @test tc[] == 1 - ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) - Base.process_events() Sys.iswindows() && Base.process_events() # schedule event (windows?) yield() # consume event @test tc[] == 2 From aaeedb10ac9b3fa954072b844f47393ebbd8baaa Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 18 Mar 2026 14:32:17 +0100 Subject: [PATCH 5/5] =?UTF-8?q?compensate=20test=20for=20"Commit=203847ff1?= =?UTF-8?q?434=20=E2=80=94=20Replace=20Base.Workqueues=20with=20a=20OncePe?= =?UTF-8?q?rThread=20=20=20(#58941)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/channels.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/channels.jl b/test/channels.jl index f646b41cfa1a0..c38574a8e08f2 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -464,10 +464,11 @@ end @test isopen(async) ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) - @test isempty(Base.Workqueue) + W = Base.workqueue_for(Threads.threadid()) + @test isempty(W) Base.process_events() # schedule event Sys.iswindows() && Base.process_events() # schedule event (windows?) - @test length(Base.Workqueue) == 1 + @test length(W) == 1 ccall(:uv_async_send, Cvoid, (Ptr{Cvoid},), async) @test tc[] == 0 yield() # consume event