Cannot catch Ctrl-C gracefully in this script

This is related to this issue.

Put the following into a script file.jl:

function try_interrupt()
    while true
        try
            sleep(1)
            println("trying...")
            @async 1+1
        catch e
            if typeof(e) <: InterruptException
                println("caught Interrupt")
                return
            end
        end
    end
    return
end

try_interrupt()

If I run the script in any of the following ways, I cannot gracefully interrupt the loop with Ctrl-C:

  • julia file.jl
  • julia -i file.jl
  • julia -e 'include(popfirst!(ARGS))' file.jl

The error looks like:

trying...
trying...
^Cfatal: error thrown and no exception handler available.
InterruptException()
jl_mutex_unlock at /buildworker/worker/package_linux64/build/src/julia_locks.h:129 [inlined]
jl_task_get_next at /buildworker/worker/package_linux64/build/src/partr.c:484
poptask at ./task.jl:827
wait at ./task.jl:836
task_done_hook at ./task.jl:544
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2247 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2429
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1788 [inlined]
jl_finish_task at /buildworker/worker/package_linux64/build/src/task.c:218
start_task at /buildworker/worker/package_linux64/build/src/task.c:888

Note that it works if I run the code in the REPL.

The last one is from the docs, where it specifically says I can use it to catch InterruptException.

This is my versioninfo():

Julia Version 1.7.2
Commit bf53498635 (2022-02-06 15:21 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-6850K CPU @ 3.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, broadwell)

Any help is welcome, thank you!

Seems to work for me on (Windows) Julia 1.7.2 and Julia 1.8.0-beta3, i.e. not reproducible here. Sorry for not being helpful.

Edit: try to clarify.

Despite you naming it try_segfault, I don’t think this is actually a segment[ation] fault, but that’s a nitpick (in your case, nor mine despite “unknown function (ip: (nil))” which I have and you don’t; I don’t think you would get a stack-trace, for a segfault?).

You might want to open an issue about this, but just give the facts. Please check this in the latest 1.9 master (and 1.6.5), and report against it. Julia 1.8 should be out any day now, so it’s likely not helpful to ask for a backport to 1.7.x, but to 1.8.x would be good, and to 1.6.x. I didn’t check 1.6.5 or 1.7.2.

I tried your script or even an empty infinite loop, starting with:

atexit(exit)

I got similar results. Note, not with atexit(exit()) # then I got a confusing, at first, error.

I’m on Linux, and I get similar as you in my julia-1.9-DEV-76cf1761e6 (and also in 1.3.1):

 trying...
^C
signal (2): Interrupt
in expression starting at /home/pharaldsson_sym/gdp_speed/gdp_speeds/ctrlc.jl:25
epoll_wait at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
uv__io_poll at /workspace/srcdir/libuv/src/unix/epoll.c:240
uv_run at /workspace/srcdir/libuv/src/unix/core.c:383
ijl_task_get_next at /buildworker/worker/package_linux64/build/src/partr.c:556
poptask at ./task.jl:884
wait at ./task.jl:893
task_done_hook at ./task.jl:597
jfptr_task_done_hook_54049.clone_1 at /home/pharaldsson_sym/julia-1.9-DEV-76cf1761e6/lib/julia/sys.so (unknown line)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2349 [inlined]
ijl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2531
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1825 [inlined]
jl_finish_task at /buildworker/worker/package_linux64/build/src/task.c:254
start_task at /buildworker/worker/package_linux64/build/src/task.c:942
unknown function (ip: (nil))
Allocations: 2904 (Pool: 2892; Big: 12); GC: 0

What was the point of @async line? Then I get a longer error, when you report you may want to omit it, or show with if it’s supposed to be there, or maybe show both.

Note, I reported a bug previously about CTRL-C not working, and it didn’t for your code in my Julia 1.7.0:

That issue was closed, so I assumed fixed, but maybe not. See also the open issue linked from it at the bottom. Please report what you think relevant and maybe link to this discussion.

If you mean as intended, just exiting, i.e. not working the same, with the error, that’s also relevant info to report.

Despite you naming it try_segfault, I don’t think this is actually a segment[ation] fault

You are right, I edited the post

What was the point of @async line?

Good question, I don’t know… I got the code from here. I will do more tests both with and without it.

I will open an issue about this. Thank you for your suggestions!

Because running a script does not throw InterruptException when you try to terminate it with CTRL-C (SIGINT) (docs), you got the error even without @async line. To avoid it, use julia -i "file.jl" or julia -e 'include(popfirst!(ARGS))' file.jl.

The @async line has to be there to have the error using julia -i "file.jl"

1 Like

This is the opened issue on Github: https://github.com/JuliaLang/julia/issues/45055

2 Likes

Have you tried running julia --handle-signals=no to disable julia’s own signal handling?

1 Like

I just tried with just released 1.10.0, julia --handle-signals=no -i file.jl and I get this error:

trying...
trying...
^CError: Maybe we should never reach this?

Is this better? I honestly don’t know …

Linking this related post in case it helps.

Thank you for the suggestion. I need to change Void to Cvoid to execute the file (is it correct?). But then the problem persists.

Perhaps try:

ccall(:jl_exit_on_sigint, Nothing, (Cint,), 0)

I tried but the problem persists.

Sorry for the bad pointer.

To handle the @async case, I don’t know what the Julia equivalent of Python’s asyncio.run() solution is.