Skip to content

Commit

Permalink
✨ change to child wake process to terminate and listen the behavior i…
Browse files Browse the repository at this point in the history
…n parent process. parent process exit with keyboard interrupt when all child process done with keyboard interrupt.
  • Loading branch information
MeditationDuck committed Sep 18, 2024
1 parent f041dd4 commit 2d12e0c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
27 changes: 19 additions & 8 deletions wake/testing/pytest_plugin_multiprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(
self._debug = debug
self._exception_handled = False

self.keyboard_interrupt = False
self._ctx_managers = []

def _setup_stdio(self):
Expand All @@ -87,13 +88,9 @@ def _exception_handler(
e: Optional[BaseException],
tb: Optional[TracebackType],
) -> None:
ignored_exceptions = (
websocket._exceptions.WebSocketConnectionClosedException,
ConnectionResetError,
BrokenPipeError,
KeyboardInterrupt
)
if e_type in ignored_exceptions:

# After the keyboard interrupt, we do not interested in debugging.
if self.keyboard_interrupt:
return

self._cleanup_stdio()
Expand All @@ -117,6 +114,11 @@ def _exception_handler(
finally:
self._setup_stdio()
self._conn.send(("exception_handled",))

# def pytest_keyboard_interrupt(self, excinfo: pytest.ExceptionInfo[BaseException]):
# print("Keyboard interrupt")
# self.keyboard_interrupt = True
# self._queue.put(("keyboard_interrupt", self._index))

def pytest_configure(self, config: pytest.Config):
self._f = open(self._log_file, "w")
Expand Down Expand Up @@ -188,7 +190,13 @@ def coverage_callback() -> None:
pass

pickling_support.install()
signal.signal(signal.SIGINT, signal.SIG_IGN)

def sigint_handler(signum, frame):
self.keyboard_interrupt = True
self._queue.put(("keyboard_interrupt", self._index))
pytest.exit(returncode=0)

signal.signal(signal.SIGINT, sigint_handler)

if self._debug:
set_exception_handler(self._exception_handler)
Expand Down Expand Up @@ -233,6 +241,9 @@ def pytest_runtest_protocol(self, item, nextitem):
# do not forward pytest_runtest_logstart and pytest_runtest_logfinish as they write item location to stdout which may be different for each process

def pytest_runtest_logreport(self, report: pytest.TestReport):
# not sending exception report since the reason of exception is keyboard interrupt or at least triggered by keyboard interrupt
if self.keyboard_interrupt:
return
self._queue.put(("pytest_runtest_logreport", self._index, report))

def pytest_warning_recorded(self, warning_message, when, nodeid, location):
Expand Down
19 changes: 13 additions & 6 deletions wake/testing/pytest_plugin_multiprocess_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from contextlib import nullcontext
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union

import signal
import os
import pytest
import rich.progress
import rich.traceback
Expand Down Expand Up @@ -101,14 +102,15 @@ def pytest_sessionstart(self, session: pytest.Session):
parent_conn,
)
p.start()

signal.signal(signal.SIGINT, signal.SIG_IGN)

def pytest_sessionfinish(self, session: pytest.Session):
self._queue.cancel_join_thread()
for p, conn in self._processes.values():
p.terminate()
if p.pid is not None:
os.kill(p.pid, signal.SIGINT)
p.join()
conn.close()

self._queue.close()

# flush coverage
Expand Down Expand Up @@ -177,6 +179,7 @@ def pytest_runtestloop(self, session: pytest.Session):
)

try:
keyboard_interrupt = [False for _ in range(self._proc_count)]
with ctx as progress:
if progress is not None:
tasks = [
Expand Down Expand Up @@ -268,7 +271,7 @@ def pytest_runtestloop(self, session: pytest.Session):
)
elif msg[0] == "pytest_sessionfinish":
if progress is not None:
text = f"#{index} finished [green]✓[/green]" if msg[2] == 0 else f"#{index} failed [red]✗[/red]"
text = f"#{index} finished [green]✓[/green]" if msg[2] == 0 or keyboard_interrupt[index] else f"#{index} failed [red]✗[/red]"
progress.update(tasks[index], description=text)

self._processes.pop(index)
Expand All @@ -280,8 +283,12 @@ def pytest_runtestloop(self, session: pytest.Session):
session.config.hook.pytest_internalerror(
excrepr=exc_info.getrepr(style="short"), excinfo=exc_info
)
elif msg[0] == "keyboard_interrupt":
keyboard_interrupt[index] = True

if False not in keyboard_interrupt:
raise KeyboardInterrupt
finally:
print("")
for report in reports:
session.config.hook.pytest_runtest_logreport(report=report)

Expand Down

0 comments on commit 2d12e0c

Please sign in to comment.