JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.87k stars 5.49k forks source link

Ctrl+c on `@threads` loop causes Julia exit rather than error #56462

Open thchr opened 2 weeks ago

thchr commented 2 weeks ago

Ctrl+c'ing during the execution of the code below causes Julia to crash, returning to the terminal:

tchr$ julia +release -t8
[...]
julia> t = time();

julia> Threads.@threads for i in 1:100
           sleep(5)
           println(i, ": ", round(Int, time()-t), " s")
       end
40: 6 s
1: 6 s
65: 6 s
89: 6 s
27: 6 s
53: 6 s
77: 6 s
14: 6 s
2: 11 s
54: 11 s
78: 11 s
90: 11 s
41: 11 s
15: 11 s
66: 11 s
28: 11 s
^C^C6755: 16 s # <----- I press "ctrl+c" here
29: 16 s
79: 16 s
42: 16 s
91: 16 s
3: 16 s
fatal: error thrown and no exception handler available.
ErrorException("attempt to switch to exited task")
try_yieldto at ./task.jl:958
wait at ./task.jl:1022
task_done_hook at ./task.jl:694
jfptr_task_done_hook_65631.1 at /home/tchr/.julia/juliaup/julia-1.11.1+0.x64.linux.gnu/lib/julia/sys.so (unknown line)
jl_apply at /cache/build/builder-demeter6-6/julialang/julia-master/src/julia.h:2157 [inlined]
jl_finish_task at /cache/build/builder-demeter6-6/julialang/julia-master/src/task.c:319
start_task at /cache/build/builder-demeter6-6/julialang/julia-master/src/task.c:1213
tchr$ # <--- I'm returned to my terminal

I suspect there may be an existing issue for this - but couldn't find one. If there is though - or if it is simply the best that can be hoped for under threaded conditions (or if I'm doing something forbidden!) - simply close this.

versioninfo() is (seen on both 1.10.6 and 1.11 and on both WSL2 and "plain" Windows):

julia> versioninfo()
Julia Version 1.11.1
Commit 8f5b7ca12ad (2024-10-16 10:53 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, tigerlake)
Threads: 8 default, 0 interactive, 4 GC (on 8 virtual cores)
Environment:
  JULIA_EDITOR = code
  JULIA_PKG_PRESERVE_TIERED_INSTALLED = true
bencardoen commented 1 week ago

@thchr See this thread for some background on this, this also occurs on Linux (and has been the case iirc for 1.6 onwards) https://discourse.julialang.org/t/interrupt-threads-threads-computation/71199/7

And the related issue: https://github.com/JuliaLang/julia/issues/35524

The short answer is that to interrupt multithreaded code by a user signal, you'll (depending on your actual use case) need to

Several edge cases exist, if you want to interrupt a thread before it checks (which happens for me during debugging, for example), that is non-trivial to do, checking the flag becomes a performance issue in certain situations as well.

For my use cases, interrupted threaded blocks often is cleaner with a killed REPL compared to a REPL where I don't know what memory/data structures may be corrupted, but that is very user and use case specific, the above issue and discussion have probably more in depth discussion/use cases and workarounds.

Thuener commented 6 days ago

Maybe this issues was already fixed? This worked for me on version 1.10.2:

julia> t = time()
1.732015459896e9

julia> Threads.@threads for i in 1:100
                  try
                      sleep(5)
                      println(i, ": ", round(Int, time()-t), " s")
                  catch e
                      println(e)
                      return nothing
                  end
              end
1: 6 s
2: 11 s  (Ctrl+C)
InterruptException()

Version info: Julia Version 1.10.2 Commit bd47eca2c8 (2024-03-01 10:14 UTC) Build Info: Official https://julialang.org/ release Platform Info: OS: Windows (x86_64-w64-mingw32) CPU: 8 × 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-15.0.7 (ORCJIT, tigerlake) Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)

bencardoen commented 5 days ago

@Thuener Not for me on Linux at least, (julia +1.11). Your post says Threads:1, on Windows (sometimes) JULIA_NUM_THREADS can default to 1 instead of auto (all cores).

You can check by julia -e 'using Base.Threads; @info nthreads()'