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
Workaround so only one CTRL-C is required for a new prompt in --gui=qt #3219
Changes from 3 commits
0cc40b1
f334300
bcdeb79
251778c
7976a1e
3918006
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,11 @@ | |
# Imports | ||
#----------------------------------------------------------------------------- | ||
|
||
import os | ||
import signal | ||
import time | ||
import threading | ||
|
||
from IPython.core.interactiveshell import InteractiveShell | ||
from IPython.external.qt_for_kernel import QtCore, QtGui | ||
from IPython.lib.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready | ||
|
@@ -116,8 +121,21 @@ def inputhook_qt4(): | |
except KeyboardInterrupt: | ||
ignore_CTRL_C() | ||
got_kbdint[0] = True | ||
print("\nKeyboardInterrupt - Ctrl-C again for new prompt") | ||
mgr.clear_inputhook() | ||
if(os.name == 'posix'): | ||
pid = os.getpid() | ||
print("^C") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for this print statement here, as it doesn't match how the shell behaves in other cases:
That means that if we ever add an explicit |
||
|
||
timer = threading.Timer( .01, | ||
os.kill, | ||
args=[pid, signal.SIGINT] | ||
) | ||
|
||
timer.start() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what would happen if you did join here - I've never understood how this particular bit works, where does the code need to be for this to be properly handled? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way ipython seem to integrate with qt eventloop is by registering a callback that gets executed periodically when Python is waiting for input. The callback runs the qt eventloop for 50 ms so all the mouse/windowing stuff gets handled. The problem is you can't raise exceptions in this callback, so CTRL-C won't work at all. The original author got around this by catching the SIGINT, and the disabling the callback (which means the next CTRL-C will be caught by python proper and not the callback). I tried to get around that by making it send a ctrl-c to itself after the first ctrl-c, but this SIGINT has to arrive after it exits the inputhook callback, hence the need for threads/timers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assuming that the join I mentioned above is not appropriate, let's keep track of the timer instance, and cancel ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great, thanks for the explanation - I figured it was something like that, I just wanted to understand. |
||
else: | ||
print("\nKeyboardInterrupt - Ctrl-C again for new prompt") | ||
|
||
|
||
except: # NO exceptions are allowed to escape from a ctypes callback | ||
ignore_CTRL_C() | ||
from traceback import print_exc | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a short descriptive comment before this
if
that indicates what the intent is and why it's done withos.kill
and a timer. It will help anyone who in the future has to revisit this code.