Exemplo n.º 1
0
def cpu_bound(task_id: Optional[int] = None,
              send_process_id: bool = False) -> str:
    """
    CPU-bound operations will block the event loop:
    in general it is preferable to run them in a process pool.
    """
    try:
        logger = getLogger(__name__)

        def hander(_signum: int, _frame: Optional[Any]) -> NoReturn:
            logger.info("CPU-bound: Terminate")
            raise Terminated()

        signal(SIGTERM, hander)
        process_id = os.getpid()
        print(process_id)
        logger.info("CPU-bound: process id = %d", process_id)
        if send_process_id:
            time.sleep(SECOND_SLEEP_FOR_TEST_MIDDLE)
            logger.info("CPU-bound: Send process id")
            LocalSocket.send(str(process_id))
        logger.info("CPU-bound: Start")
        result = sum(i * i for i in range(10**7))
        logger.debug("CPU-bound: Finish")
        logger.debug("%d %s", task_id, datetime.now())
        return ("" if task_id is None else
                f"task_id: {task_id}, ") + f"result: {result}"
    except KeyboardInterrupt:
        logger.info("CPU-bound: KeyboardInterupt")
        raise
Exemplo n.º 2
0
 def test_sigterm(manager_queue: "queue.Queue[LogRecord]") -> None:
     """ProcessTaskPoolExecutor should raise keyboard interrupt."""
     process = Process(target=example_use_case_cancel_repost_process_id, kwargs={"queue_main": manager_queue})
     process.start()
     LocalSocket.receive()
     time.sleep(SECOND_SLEEP_FOR_TEST_SHORT)
     psutil_process = psutil.Process(process.pid)
     psutil_process.send_signal(SIGTERM)
     psutil_process.wait()
     # Reason: Requires to enhance types-psutil
     assert not psutil_process.is_running()  # type: ignore
     assert_graceful_shutdown(manager_queue)
Exemplo n.º 3
0
 def test_keyboard_interrupt(self) -> None:
     """Tests keyboard interrupt and send response to pytest by socket when succeed."""
     try:
         self.test()
     except BaseException as error:
         self.logger.exception(error)
         traceback.print_exc()
         LocalSocket.send("Test failed")
         raise
     else:
         LocalSocket.send("Test succeed")
     finally:
         asyncio.run(asyncio.sleep(10))
Exemplo n.º 4
0
 def test_keyboard_interrupt_on_linux(self) -> None:
     """
     - Keyboard interrupt should reach to all descendant processes.
     - Keyboard interrupt should shutdown ProcessTaskPoolExecutor gracefully.
     """
     process = Process(target=self.report_raises_keyboard_interrupt)
     process.start()
     LocalSocket.receive()
     time.sleep(SECOND_SLEEP_FOR_TEST_SHORT)
     self.simulate_ctrl_c_in_posix(process)
     assert LocalSocket.receive() == "Test succeed"
     process.join()
     assert process.exitcode == 0
     assert not process.is_alive()
Exemplo n.º 5
0
def example_use_case_cancel_repost_process_id(
        queue_sub: Optional["queue.Queue[LogRecord]"] = None,
        queue_main: Optional["queue.Queue[LogRecord]"] = None) -> None:
    """The example use case of ProcessTaskPoolExecutor for E2E testing in case of cancel."""
    time.sleep(SECOND_SLEEP_FOR_TEST_SHORT)
    LocalSocket.send(str(os.getpid()))
    if queue_main:
        logger = getLogger()
        logger.addHandler(QueueHandler(queue_main))
        logger.setLevel(DEBUG)
    results = example_use_case_method(queue_sub)
    results_string = repr(results)
    LocalSocket.send(results_string)
    pytest.fail(results_string)
async def get_process_id() -> int:
    print("Await socket")
    process_id = int(LocalSocket.receive())
    print("Await sleep")
    await asyncio.sleep(SECOND_SLEEP_FOR_TEST_WINDOWS_NEW_WINDOW)
    print("Kill group lead process")
    return process_id
Exemplo n.º 7
0
 def test_keyboard_interrupt_ctrl_c_new_process_group() -> None:
     """
     see:
       - On Windows, what is the python launcher 'py' doing that lets control-C cross between process groups?
         https://stackoverflow.com/q/42180468/12721873
         https://github.com/njsmith/appveyor-ctrl-c-test/blob/34e13fab9be56d59c3eba566e26d80505c309438/a.py
         https://github.com/njsmith/appveyor-ctrl-c-test/blob/34e13fab9be56d59c3eba566e26d80505c309438/run-a.py
     """
     with Popen(
         f"{sys.executable} tests\\testlibraries\\keyboaard_interrupt_in_windows.py",
         # Reason: Definition of following constant is Windows only
         creationflags=CREATE_NEW_PROCESS_GROUP,  # type: ignore
     ) as popen:
         asyncio.run(asyncio.sleep(SECOND_SLEEP_FOR_TEST_MIDDLE))
         LocalSocket.send(str(popen.pid))
         assert LocalSocket.receive() == "Test succeed"
         assert popen.wait() == 0
Exemplo n.º 8
0
 def test_keyboard_interrupt_ctrl_c_new_window() -> None:
     """
     see:
       - Answer: Sending ^C to Python subprocess objects on Windows
         https://stackoverflow.com/a/7980368/12721873
     """
     with Popen(f"start {sys.executable} tests\\testlibraries\\subprocess_wrapper_windows.py", shell=True) as popen:
         assert LocalSocket.receive() == "Test succeed"
         assert popen.wait() == 0
 def test_coroutine() -> None:
     """CPU bound should be terminated when coroutine."""
     with ProcessPoolExecutor() as executor:
         future = executor.submit(cpu_bound, 1, True)
         pid = LocalSocket.receive()
         print(pid)
         psutil_process = psutil.Process(int(pid))
         psutil_process.terminate()
         assert isinstance(future.exception(), Terminated)
         assert future.done()
Exemplo n.º 10
0
 def test_terminate(manager_queue: "queue.Queue[LogRecord]") -> None:
     """
     Can't test in case process.kill() since it sends signal.SIGKILL and Python can't trap it.
     Function process.kill() stops pytest process.
     see:
       - https://psutil.readthedocs.io/en/latest/#psutil.Process.terminate
       - https://psutil.readthedocs.io/en/latest/#psutil.Process.kill
       - https://docs.python.org/ja/3/library/signal.html#signal.SIGKILL
     """
     process = Process(target=example_use_case_cancel_repost_process_id, kwargs={"queue_main": manager_queue})
     process.start()
     LocalSocket.receive()
     time.sleep(SECOND_SLEEP_FOR_TEST_SHORT)
     psutil_process = psutil.Process(process.pid)
     psutil_process.terminate()
     psutil_process.wait()
     # Reason: Requires to enhance types-psutil
     assert not psutil_process.is_running()  # type: ignore
     assert_graceful_shutdown(manager_queue)
Exemplo n.º 11
0
 async def execute_test(future: "Future[Any]", signal_number: int,
                        expect: bool,
                        expect_type_error: Type[BaseException]) -> None:
     """Executes test."""
     process_task = ProcessTask(int(LocalSocket.receive()))
     assert future.done() == expect
     assert future.cancelled() == expect
     await asyncio.sleep(SECOND_SLEEP_FOR_TEST_SHORT)
     with pytest.raises(expect_type_error):
         process_task.send_signal(signal_number)
         await future
 def test_method() -> None:
     """CPU bound should be terminated when method."""
     parent_conn, child_conn = multiprocessing.Pipe()
     process = Process(target=process_cpu_bound_method,
                       args=(1, True, child_conn))
     process.start()
     pid = LocalSocket.receive()
     print(pid)
     psutil_process = psutil.Process(int(pid))
     psutil_process.terminate()
     process.join()
     assert not parent_conn.poll()
Exemplo n.º 13
0
 async def test_future() -> None:
     """
     Can't test in case process.kill() since it sends signal.SIGKILL and Python can't trap it.
     Function process.kill() stops pytest process.
     see:
       - https://psutil.readthedocs.io/en/latest/#psutil.Process.terminate
       - https://psutil.readthedocs.io/en/latest/#psutil.Process.kill
       - https://docs.python.org/ja/3/library/signal.html#signal.SIGKILL
     """
     with ProcessTaskPoolExecutor(cancel_tasks_when_shutdown=True) as executor:
         future = executor.create_process_task(process_cpu_bound, 1, True)
         pid = LocalSocket.receive()
         process = psutil.Process(int(pid))
         process.terminate()
         with pytest.raises(Terminated):
             await future
         assert future.done()
         assert isinstance(future.exception(), Terminated)
Exemplo n.º 14
0
 def report_raises_keyboard_interrupt() -> None:
     with pytest.raises(KeyboardInterrupt):
         example_use_case_cancel_repost_process_id()
     LocalSocket.send("Test succeed")