Catch ctrl-c in script

From the Julia docs:

Running a Julia script using julia file.jl does not throw InterruptException when you try to terminate it with CTRL-C (SIGINT). To run a certain code before terminating a Julia script, which may or may not be caused by CTRL-C, use atexit. Alternatively, you can use julia -e 'include(popfirst!(ARGS))' file.jl to execute a script while being able to catch InterruptException in the try block. Note that with this strategy PROGRAM_FILE will not be set.

Here is a simple script trying to test this:

is_running = Ref(true)

t = @async while is_running[]
    println("Hello!")
    sleep(1)
end

atexit() do
    is_running[] = false
    println("Goodbye!")
    wait(t)
    exit()
end

wait(t)

However, when I run this script with julia test.jl, I get the following terminal output:

Hello!
^C
[96503] signal (2): Interrupt
in expression starting at /home/mcooper/gnc_tools/delete_this/test2.jl:15
epoll_wait at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
uv__io_poll at /workspace/srcdir/libuv/src/unix/epoll.c:236
uv_run at /workspace/srcdir/libuv/src/unix/core.c:400
ijl_task_get_next at /cache/build/builder-amdci5-1/julialang/julia-release-1-dot-10/src/partr.c:470
poptask at ./task.jl:985
wait at ./task.jl:994
#wait#645 at ./condition.jl:130
wait at ./condition.jl:125 [inlined]
_trywait at ./asyncevent.jl:142
wait at ./asyncevent.jl:159 [inlined]
sleep at ./asyncevent.jl:265 [inlined]
#105 at /home/mcooper/.julia/packages/Revise/uvGMC/src/packagedef.jl:1340
unknown function (ip: 0x78f864f01432)
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-release-1-dot-10/src/gf.c:2894 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-release-1-dot-10/src/gf.c:3076
jl_apply at /cache/build/builder-amdci5-1/julialang/julia-release-1-dot-10/src/julia.h:1982 [inlined]
start_task at /cache/build/builder-amdci5-1/julialang/julia-release-1-dot-10/src/task.c:1238
unknown function (ip: (nil))
Allocations: 2907 (Pool: 2899; Big: 8); GC: 0
Goodbye!

I can see that “Goodbye!” did get printed above, but it is there a way to stop the segmentation fault?

Cheers for the help.

You could try calling Base.exit_on_sigint(false) and then swallow the InterruptException that wait throws with try catch

1 Like

Thank you that works and the program exits cleanly. However, one downside is that I need all these try and catch statements everywhere now. For example if I had two async tasks, it would look like as follows:

Base.exit_on_sigint(false)

t1 = @async while true
    try
        println("Hello")
        sleep(1)
    catch
        println("Caught an exception!")
        exit()
    end
end

t2 = @async while true
    try
        println("World!")
        sleep(1)
    catch
        println("Caught an exception!")
        exit()
    end
end

wait.([t1, t2])

Do you know if there is anyway to simplify this? Cheers.