Commit 9cc4da8a authored by Matias Guijarro's avatar Matias Guijarro
Browse files

ctrl-c handling: make SIGINT killing the current eval greenlet via libev watcher

Instead of letting normal handling with KeyboardInterrupt happening potentially anywhere
parent c3802eda
......@@ -6,7 +6,10 @@
# Distributed under the GNU LGPLv3. See LICENSE for more info.
"""PtPython REPL with no threads"""
import signal
import gevent
import asyncio
import aiogevent
from typing import Optional
from ptpython.repl import PythonRepl, set_title, clear_title
......@@ -48,6 +51,17 @@ class NoThreadPythonRepl(PythonRepl):
completely.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._current_eval_g = None # greenlet of the command being executed in shell
self._sigint_handler = gevent.signal_handler(signal.SIGINT, self._handle_ctrl_c)
def _handle_ctrl_c(self):
if self._current_eval_g:
self._current_eval_g.kill(KeyboardInterrupt)
def _create_buffer(self) -> Buffer:
"""
Create the `Buffer` for the Python input.
......@@ -159,7 +173,7 @@ class NoThreadPythonRepl(PythonRepl):
# Eval.
try:
result = await self.eval_async(text)
result = await self.eval_greenlet(text)
except KeyboardInterrupt as e: # KeyboardInterrupt doesn't inherit from Exception.
raise
except SystemExit:
......@@ -186,3 +200,7 @@ class NoThreadPythonRepl(PythonRepl):
if self.terminal_title:
clear_title()
self._remove_from_namespace()
def eval_greenlet(self, text):
self._current_eval_g = gevent.spawn(self.eval, text)
return aiogevent.wrap_greenlet(self._current_eval_g)
......@@ -676,12 +676,11 @@ def embed(*args, **kwargs):
"""
use_tmux = kwargs.get("use_tmux", False)
scans_display = ScanDisplayDispatcher()
if not is_windows() and use_tmux:
scans_display.set_use_progress_bar(True)
with filter_warnings():
cmd_line_i = cli(*args, **kwargs)
scans_display = ScanDisplayDispatcher(cmd_line_i)
if not is_windows() and use_tmux:
scans_display.set_use_progress_bar(True)
with patch_stdout_context(raw=True):
asyncio.run(cmd_line_i.run_async())
......@@ -659,7 +659,9 @@ class ScanDisplayDispatcher(ScanHooks):
"""Listen scans from the BLISS session and dispatch them to dedicated scan
displayer"""
def __init__(self):
def __init__(self, bliss_repl):
self._repl = bliss_repl
set_scan_watch_callbacks(self.on_scan_new, self.on_scan_data, self.on_scan_end)
self._scan_displayer = None
"""Current scan displayer"""
......@@ -686,7 +688,7 @@ class ScanDisplayDispatcher(ScanHooks):
# Scans started from the background are ignored
current = gevent.getcurrent()
if current.parent is not None:
if current is not self._repl._current_eval_g:
return None
if self._use_progress_bar:
......
# Conda requirements file
aiogevent >= 0.4
aiogevent >= 0.4.1
cerberus
colorama
cython
......
# Conda requirements file
black == 18.6b4 # Dependency with ptpython, BLISS test, BLISS dev. Better to manage the constraint here
aiogevent >= 0.4
aiogevent >= 0.4.1
blessings
cerberus
colorama
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment