-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KeyboardInterrupt support / SIGINT handler #211
Comments
I have a way to raise # tmp.py
import signal
from time import sleep
from typing import Any
import julia
julia.Julia(sysimage="sys.so")
from julia import Main
def my_sig_handler(signalnum: int, frame: Any) -> Any:
sig = signal.Signals(signalnum)
print(f"\nGot {sig=}")
raise KeyboardInterrupt
# unblock SIGINT and set up a handler
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])
signal.signal(signal.SIGINT, my_sig_handler)
# Other signals can be handled too, e.g. SIGUSR1:
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1])
signal.signal(signal.SIGUSR1, my_sig_handler)
while True:
print("sleeping")
sleep(1) Here is what usage looks like at the command-line:
|
Hi @tkf and @Jasha10, For context: I am in the process of porting the package "PySR" to PyJulia (MilesCranmer/PySR#87) rather than the current strategy of executing a Julia script. Having a working KeyboardInterrupt is the last item I am trying to fix before I merge things - it is quite important for the package because there are long-running executions which need to be stopped by the user. Are there any currently known workarounds I could look at using? |
Let me record my recent observations. Python signal-handling setup:Suppose you have a python script that uses pyjulia (via e.g. import signal
def sig_handler_keyboard_interrupt(signalnum, frame): raise KeyboardInterrupt
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])
signal.signal(signal.SIGINT, sig_handler_keyboard_interrupt) NOTE: For the above to have an effect, the calls to Effects of the signal-handling setupYour python script may do computations in julia (e.g.
Thus we have a "pick-your-poison" situation. I do not know whether there is a way to have one signal (SIGINT) interrupt both python computation and julia computation. Additional notesIt seems that julia-side signal handling is not yet implemented in the standard library, so currently signal handling on the python side seems like the way to go. signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1])
signal.signal(signal.SIGUSR1, sig_handler_keyboard_interrupt) This way, SIGINT could be used to interrupt julia computation and SIGUSR1 could be used to interrupt python computation. |
Currently PyJulia does not support
KeyboardInterrupt
. That is to say, in long-running Python and Julia computation, there is no way to terminate a sub-computation by catchingKeyboardInterrupt
as done in normal Python programming.Aside: Recommended way to cancel current input in REPL is to use IPython 7.0 or above. Ctrl-C would cancel the input without causing SIGINT.
This problem is previously mentioned in: #189, #185 (comment)
What follows is a summary of my understanding:
When PyJulia is initialized, libjulia takes over all signal handling. I couldn't find a way to disable this behavior. Julia documentation mentions that "Julia requires a few signal to function property." so it probably would not have something like
Py_InitializeEx
to initialize libjulia without installing signal handlers anytime soon.What would be more easily achievable is to let Julia translate SIGINT to
InterruptException
and then let PyCall to translate it to Python'sKeyboardInterrupt
. I have implemented it in JuliaPy/PyCall.jl#574 but it introduced a bug which is hard to track. I reported it in Julia: JuliaLang/julia#29498. Note that this strategy is not perfect because long-running pure-Python computation or I/O cannot respond to SIGINT. If Julia implements some kind of signal handling JuliaLang/julia#14675 then maybe we can callPyErr_SetInterrupt
(which does not need GIL) from it.The text was updated successfully, but these errors were encountered: