From the REPL, how do I interrupt execution of a function? Basically, I want to press some command key and cause it to throw an error that I can catch. For example:
# some computation
println("function terminated by user")
From reading some old threads, I got the impression that (on Windows) pressing
ctrl+c would do what I want. I find that it does nothing unless I press it four times rapidly, in which case it kills the whole Julia session, not merely throw an error. Same thing in Juno.
(This is on Julia 1.0.0).
ctrl-c is to interrupt a calculation but it doesn’t always work. If you want to use it with a try-catch do:
# some computation
if e isa InterruptException
println("function terminated by user")
# do something else
Are you saying there is no reliable way to interrupt a calculation? If so, is there any way to predict the conditions under which it will/won’t work?
I am not sure what you mean by “no reliable way to interrupt a calculation”. At least pulling the power plug is definitely a reliable way to interrupt it
Wrapping the part of the code which you want to allow to be interrupted in a try/catch block and expecting the interrupt exception is pretty common (and reliable, as long is it is not caught before it bubbles up to that point). I use this construct also in Python all the time and it works reliably (
KeyboardInterrupt in that case).
I said “reliable” because @mauro3 said that
ctrl+c doesn’t always work.
Wrapping the part of the code which you want to allow to be interrupted in a try/catch block and expecting the interrupt exception is pretty common (and reliable, as long is it is not caught before it bubbles up to that point)
If I understand you correctly, the type of code I posted above (and @mauro3’s more refined version) should, when I press
ctrl+c, exit the loop and enter the
catch clause. But in the simple case I have tried (where the loop body does something trivial, like increment a counter), pressing
ctrl+c does nothing, unless you press it so rapidly it just kills the session, which is not what I want.
OK that indeed is strange. I saw this happening with code which caught the exception one layer below… I’d consider this a bug if it is not the case for the code above.
Can you post the exact code you tried?
Having to press it multiple times is perfectly normal if your computation doesn’t allocate. Exiting the repl could be something else, most likely Windows specific.
Can you be more specific? Why does no allocation implies that the
InterruptException is ignored?
It does not. It can be delayed. Allocation is simply a common place the exception can be delivered but it’s far from the only one.
Aha, we are getting somewhere. When I employed the
try/catch structure above in my real code (where the loop body involved something substantial), pressing
ctrl+c worked. It appears that the loop body in my test was so simple that it didn’t present any/enough opportunity to check for the interrupt.
Which begs the question: If not all code can be (or is likely to be) interrupted, what kinds of code can? @yuyichao indicated code that allocates is one example.
@yuyichao: What heuristics can I use other than hope that my loop body allocates or is otherwise not “too simple” to be interruptible?
That should not be a problem. Pressing Ctrl-C multiple times should not be any different from a normal one.
It’s possible that what you’re actually executing has a different
try/catch structure than the MWE you posted above. Namely, if you end up having multiple
try/catch blocks nested (maybe from some
Base function you call which uses one internally), one of the blocks may accidentally swallow the error, continue going along its business, and then the next signal (or a few after that) may end up being the ticket to breaking all the way out to the REPL again. I don’t know if there’s really a clean way to handle this other than to ensure every
try/catch block properly handles
InterruptException, which is a lot of
Edit: One of the places I encounter these sorts of issues is with anything doing I/O, such as saving/loading to/from a file on disk, or doing network operations on a socket (possibly including Julia’s
@yuyichao Regardless of what should be the case, the following code:
i = 0
i += 1
println("Interrupted by user at iteration $i")
is not interruptable on my system, in the sense that pressing
ctrl+c dozens of times has no effect, unless I press it several times in rapid succession in which case it kills the Julia session instead of executing the
That’s a good guess, but there are no nested
try/catch blocks in my actual code (it’s protoype code). In fact, it’s my real code that does work and the test case in my response to @yuyichao (which I tried before trying it on my real code) that doesn’t work.
What I’m saying is that you’ve simply hit a bug on windows, regardless of what’s the heuristic for interruptable code (there isn’t any guarantee). Your code works on linux.
On my Linux machine it is not interruptible with slow ctrl-c. Fast ctrl-c will do it with:
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^CWARNING: Force throwing a SIGINT
Interrupted by user at iteration 52400256035
But I have definitely encountered situations when doing above crashed the REPL.
When it crashes on linux, it’s usually because there isn’t a better way. The whole point of the current behavior is that the exception will only be delivered when it is safe to do so. If you don’t want to wait though, you can force a delivery, with a warning as you see in the output and there’s no guarantee of the integrity of the runtime afterwards. If you are running pure julia code like this there shouldn’t be much/any problem, but if you are calling C libraries it can easily crash and there’s little julia can do about it. (The C library is usually not written to be longjmp out of and julia can’t fix it.)
The problem on windows though is that it’ll crash even when running benign julia code. I don’t know why it happens and AFAICT I didn’t touch it so it was always crashing before this behavior was introduced and now it only crashes when you force a throw. AFAICT gdb crashes when I do Ctrl-C so it’s clearly not just julia’s problem and it’s also very hard to debug. (I mean, I noticed the gdb crash when I want to use it to figure out why julia “crashed”…)
Ok. I was wondering if there was something I was doing wrong, but it appears that the behavior depends in a somewhat unpredictable way on the operating system.
I am using julia 1.4.2 , clt +c is neither kill nor stop the repl
You should create new threads instead of resurrecting old discussions, the Discourse interface should have warned you about it.
If you read the discussion above, then you know the problem can be that your code has little points in which it can be safely interrupted (like calls to IO functions like
println). I think the function
yield also create such safe points (not tested it however) without needing to print something and without any negative consequences (unless you are writing a parallel code that can have problems if you yield at that point).