From 4581ed31e34337b29f3a70bd38aa87b993fc7aea Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Sat, 8 Feb 2025 22:51:47 -0500 Subject: [PATCH] Kill the child instead of letting it die --- pyfrc/test_support/pytest_dist_plugin.py | 33 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/pyfrc/test_support/pytest_dist_plugin.py b/pyfrc/test_support/pytest_dist_plugin.py index 22c2a1c..4dc9d58 100644 --- a/pyfrc/test_support/pytest_dist_plugin.py +++ b/pyfrc/test_support/pytest_dist_plugin.py @@ -1,6 +1,8 @@ import multiprocessing +import os import pathlib import sys +import time from typing import Type @@ -34,7 +36,7 @@ def _enable_faulthandler(): faulthandler.enable() except Exception as e: - logger.warn("Could not enable faulthandler: %s", e) + logger.warning("Could not enable faulthandler: %s", e) return try: @@ -46,15 +48,25 @@ def _enable_faulthandler(): return -def _run_test(item_nodeid, config_args, robot_class, robot_file, verbose): +def _run_test(item_nodeid, config_args, robot_class, robot_file, verbose, pipe): """This function runs in a subprocess""" robotpy.logconfig.configure_logging(verbose) _enable_faulthandler() + + # keep the plugin around because it has a reference to the robot + # and we don't want it to die and deadlock + plugin = PyFrcPlugin(robot_class, robot_file, True) + ec = pytest.main( [item_nodeid, "--no-header", *config_args], - plugins=[PyFrcPlugin(robot_class, robot_file, True)], + plugins=[plugin], ) - sys.exit(ec) + + # Don't let the process die, let the parent kill us to avoid + # python interpreter badness + pipe.send(ec) + while True: + time.sleep(100) def _run_test_in_new_process( @@ -69,16 +81,21 @@ def _run_test_in_new_process( else: item_nodeid = test_function.nodeid + parent, child = multiprocessing.Pipe() + process = multiprocessing.Process( target=_run_test, - args=(item_nodeid, config_args, robot_class, robot_file, verbose), + args=(item_nodeid, config_args, robot_class, robot_file, verbose, child), ) process.start() - process.join() + try: + ec = parent.recv() + finally: + process.kill() - if process.exitcode != 0: + if ec != 0: pytest.fail( - f"Test failed in subprocess: {item_nodeid} (exit code {process.exitcode})", + f"Test failed in subprocess: {item_nodeid} (exit code {ec})", pytrace=False, )