summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2020-12-25 13:04:09 +0000
committerBernát Gábor <bgabor8@bloomberg.net>2020-12-25 13:04:39 +0000
commit0bbdf445fc7d47d0dd31599872975534243ed555 (patch)
tree446c8de3a2155a3d4a14886376e36cb076a7d807
parent631af1b0dd331c7a79c2d40ea4ef3bab1fd34632 (diff)
downloadtox-git-0bbdf445fc7d47d0dd31599872975534243ed555.tar.gz
Fix keyboard interrupt can fail
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
-rw-r--r--.pre-commit-config.yaml2
-rw-r--r--src/tox/execute/local_sub_process/read_via_thread_unix.py22
-rw-r--r--tests/execute/local_subprocess/local_subprocess_sigint.py2
-rw-r--r--tests/execute/local_subprocess/test_local_subprocess.py10
4 files changed, 21 insertions, 15 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a1387878..26a621fc 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -42,7 +42,7 @@ repos:
- --min-py3-version
- "3.6"
- repo: https://github.com/asottile/blacken-docs
- rev: v1.8.0
+ rev: v1.9.1
hooks:
- id: blacken-docs
additional_dependencies:
diff --git a/src/tox/execute/local_sub_process/read_via_thread_unix.py b/src/tox/execute/local_sub_process/read_via_thread_unix.py
index 03b5c9cf..ba156e7f 100644
--- a/src/tox/execute/local_sub_process/read_via_thread_unix.py
+++ b/src/tox/execute/local_sub_process/read_via_thread_unix.py
@@ -1,6 +1,7 @@
"""
On UNIX we use select.select to ensure we drain in a non-blocking fashion.
"""
+import errno # pragma: win32 no cover
import os # pragma: win32 no cover
import select # pragma: win32 no cover
from typing import Callable # pragma: win32 no cover
@@ -18,14 +19,19 @@ class ReadViaThreadUnix(ReadViaThread): # pragma: win32 no cover
while not self.stop.is_set():
# we need to drain the stream, but periodically give chance for the thread to break if the stop event has
# been set (this is so that an interrupt can be handled)
- ready, __, ___ = select.select([self.file_no], [], [], STOP_EVENT_CHECK_PERIODICITY_IN_MS)
- if ready:
- data = os.read(self.file_no, 1)
- if data:
- try:
- self.handler(data)
- except Exception: # noqa
- pass
+ try:
+ ready, __, ___ = select.select([self.file_no], [], [], STOP_EVENT_CHECK_PERIODICITY_IN_MS)
+ if ready:
+ data = os.read(self.file_no, 1)
+ if data:
+ try:
+ self.handler(data)
+ except Exception: # noqa
+ pass
+ except OSError as exception:
+ if exception.errno == errno.EBADF:
+ break
+ raise
def _drain_stream(self) -> bytes:
result = bytearray() # on closed file read returns empty
diff --git a/tests/execute/local_subprocess/local_subprocess_sigint.py b/tests/execute/local_subprocess/local_subprocess_sigint.py
index 16d0b4c9..928d41b8 100644
--- a/tests/execute/local_subprocess/local_subprocess_sigint.py
+++ b/tests/execute/local_subprocess/local_subprocess_sigint.py
@@ -10,7 +10,7 @@ from tox.execute.api import ToxKeyboardInterrupt
from tox.execute.request import StdinSource
from tox.report import NamedBytesIO
-logging.basicConfig(level=logging.NOTSET)
+logging.basicConfig(level=logging.DEBUG, format="%(relativeCreated)d\t%(levelname).1s\t%(message)s")
bad_process = Path(__file__).parent / "bad_process.py"
executor = local_sub_process.LocalSubProcessExecutor(colored=False)
diff --git a/tests/execute/local_subprocess/test_local_subprocess.py b/tests/execute/local_subprocess/test_local_subprocess.py
index ec8a299d..d8c51107 100644
--- a/tests/execute/local_subprocess/test_local_subprocess.py
+++ b/tests/execute/local_subprocess/test_local_subprocess.py
@@ -226,16 +226,16 @@ def test_command_keyboard_interrupt(tmp_path: Path) -> None:
child = next(iter(psutil.Process(pid=root).children())).pid
process.send_signal(SIGINT)
try:
- out, err = process.communicate(timeout=5)
+ out, err = process.communicate(timeout=None)
except subprocess.TimeoutExpired: # pragma: no cover
process.kill()
out, err = process.communicate()
assert False, f"{out}\n{err}"
- assert "ERROR:root:got KeyboardInterrupt signal" in err, err
- assert f"WARNING:root:KeyboardInterrupt from {root} SIGINT pid {child}" in err, err
- assert f"WARNING:root:KeyboardInterrupt from {root} SIGTERM pid {child}" in err, err
- assert f"INFO:root:KeyboardInterrupt from {root} SIGKILL pid {child}" in err, err
+ assert "E\tgot KeyboardInterrupt signal" in err, err
+ assert f"W\tKeyboardInterrupt from {root} SIGINT pid {child}" in err, err
+ assert f"W\tKeyboardInterrupt from {root} SIGTERM pid {child}" in err, err
+ assert f"I\tKeyboardInterrupt from {root} SIGKILL pid {child}" in err, err
outs = out.split("\n")