Julia - Is there a way to prevent a block of code from being immediately interrupted by Ctrl+C/SIGINT in Julia?

Viewed 87

There is this answer for python from an old thread which I used in the past to great effect (see first answer here How to prevent a block of code from being interrupted by KeyboardInterrupt in Python?). I'd like to know if it is possible to do something similar in Julia.

That's pretty much it, but here's some background.

I'm developing a Markov Chain Monte Carlo algorithm in Julia and I need to insure that the state of the chain is always valid, especially following a Ctrl+C/SIGINT. This is particularly important during development in the REPL where I want to be able to stop the chain but then restart it where it was left off without having to start from scratch and wait for the burn-in period all over again.

As it stand it is almost always the case that the chain will be in an invalid state following a SIGINT.

In other words I want to have blocks of code that are uninterruptibles, namely critical blocks within which a SIGINT is deferred until the block has terminated.

2 Answers

Ctrl+C/SIGINT causes the InterruptException, so you can place your code within a try block and catch the InterruptException.

  try
    # ... your algorithm here ...
  catch e
    if e isa InterruptException 
      save_your_chain_to_a_valid_state()
      then_exit()
    else
      rethrow()
    end
  end

If you're running the code outside of the REPL, you'll first have to call Base.exit_on_sigint(false) before the try block.

disable_sigint prevents a block of code to be interrupted immediately, whereas catching InterruptException is a mean to handle the interrupt:

try
    disable_sigint() do
        for i in 1:5
            sleep(1)
            print(".")
        end
    end

    println("\nnow it is safe to interrupt immediately")
    while true
        sleep(1)
        print("*")
    end
catch InterruptException
    println("interrupt catched")
end

If running a script remember how to catch Ctrl-C:

julia -e 'include(pop!(ARGS))' script.jl

disable_sigint is able to mask the InterruptException generated by a SIGINT signal (for example a signal coming from a kill command on unix). For example if the running code is notified throwing directly an interruptException() it is interrupted as soon as possible ignoring the disable_sigint directive.

This may be the case of a jupyter environment where communication between client and kernel processes happens through a IPC channel (ZeroMQ transport channel) or the case of vscode where a "supervisor" process manage a child julia execution context.

Chances are that the kernel interrupt command delivered from jupiter frontend to jupyter kernel backend that "supervises" julia code is not delivered to child process using a SIGINT OS-signal.

Related