def _assert_pantsd_keyboardinterrupt_signal(self, signum: int, regexps: Optional[ List[str]] = None): """Send a signal to the thin pailgun client and observe the error messaging. :param signum: The signal to send. :param regexps: Assert that all of these regexps match somewhere in stderr. """ with self.pantsd_test_context() as (workdir, config, checker): client_handle, waiter_process_pid, _ = launch_waiter( workdir=workdir, config=config) client_pid = client_handle.process.pid waiter_process = psutil.Process(waiter_process_pid) assert waiter_process.is_running() checker.assert_started() # This should kill the client, which will cancel the run on the server, which will # kill the waiting process. os.kill(client_pid, signum) client_run = client_handle.join() client_run.assert_failure() for regexp in regexps or []: self.assertRegex(client_run.stderr, regexp) # pantsd should still be running, but the waiter process should have been killed. time.sleep(5) assert not waiter_process.is_running() checker.assert_running()
def test_sigint_kills_request_waiting_for_lock(self): """Test that, when a pailgun request is blocked waiting for another one to end, sending SIGINT to the blocked run will kill it.""" config = {"GLOBAL": {"pantsd_timeout_when_multiple_invocations": -1, "level": "debug"}} with self.pantsd_test_context(extra_config=config) as (workdir, config, checker): # Run a process that will wait forever. first_run_handle, _, file_to_create = launch_waiter(workdir=workdir, config=config) checker.assert_started() checker.assert_running() # And another that will block on the first. blocking_run_handle = self.run_pants_with_workdir_without_waiting( command=["goals"], workdir=workdir, config=config ) # Block until the second request is waiting for the lock. time.sleep(10) # Sends SIGINT to the run that is waiting. blocking_run_client_pid = blocking_run_handle.process.pid os.kill(blocking_run_client_pid, signal.SIGINT) blocking_run_handle.join() # Check that pantsd is still serving the other request. checker.assert_running() # Exit the second run by writing the file it is waiting for, and confirm that it # exited, and that pantsd is still running. safe_file_dump(file_to_create, "content!") result = first_run_handle.join() result.assert_success() checker.assert_running()
def test_ctrl_c() -> None: with temporary_workdir() as workdir: dest = os.path.join(workdir, "dest.log") # Start a pantsd run that will wait forever, then kill the pantsd client. client_handle, _, _ = launch_waiter( workdir=workdir, config=workunit_logger_config(dest)) client_pid = client_handle.process.pid os.kill(client_pid, signal.SIGINT) # Confirm that finish is still called (even though it may be backgrounded in the server). confirm_eventual_success(dest)
def test_ctrl_c() -> None: with temporary_workdir() as workdir: dest = os.path.join(workdir, "dest.log") # Start a pantsd run that will wait forever, then kill the pantsd client. client_handle, _, _ = launch_waiter(workdir=workdir, config=workunit_logger_config(dest)) client_pid = client_handle.process.pid os.kill(client_pid, signal.SIGINT) # Confirm that finish is still called (even though it may be backgrounded in the server). for _ in attempts("The log should eventually show that the SWH shut down."): content = maybe_read_file(dest) if content and FINISHED_SUCCESSFULLY in content: break
def _assert_pantsd_keyboardinterrupt_signal( self, signum: int, regexps: list[str] | None = None, not_regexps: list[str] | None = None, cleanup_wait_time: int = 0, ): """Send a signal to the thin pailgun client and observe the error messaging. :param signum: The signal to send. :param regexps: Assert that all of these regexps match somewhere in stderr. :param not_regexps: Assert that all of these regexps do not match somewhere in stderr. :param cleanup_wait_time: passed throught to waiter, dictated how long simulated cleanup will take """ with self.pantsd_test_context() as (workdir, config, checker): client_handle, waiter_pid, child_pid, _ = launch_waiter( workdir=workdir, config=config, cleanup_wait_time=cleanup_wait_time) client_pid = client_handle.process.pid waiter_process = psutil.Process(waiter_pid) child_process = psutil.Process(waiter_pid) assert waiter_process.is_running() assert child_process.is_running() checker.assert_started() # give time to enter the try/finally block in the child process time.sleep(5) # This should kill the client, which will cancel the run on the server, which will # kill the waiting process and its child. os.kill(client_pid, signum) client_run = client_handle.join() client_run.assert_failure() for regexp in regexps or []: self.assertRegex(client_run.stderr, regexp) for regexp in not_regexps or []: self.assertNotRegex(client_run.stderr, regexp) # pantsd should still be running, but the waiter process and child should have been # killed. time.sleep(5) assert not waiter_process.is_running() assert not child_process.is_running() checker.assert_running()