Unable to send the CTRL_BREAK_EVENT signal to the process in no console mode on windows (pythonw / pyinstaller)

52 Views Asked by At

We are starting a tool process using the subprocess.popen. To stop the tool we are sending ctrl+c signal so that the tool catches this & does the required clean up & report generation. It is working fine with python / pyinstaller with console.

But not working with pythonw / pyinstaller no console. It is failing with below exception

OSError: [WinError 6] The handle is invalid

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "E:\workspace\git\ABATA-Agent\t1.py", line 59, in <module>
    out, err = process.communicate()
  File "C:\Program Files\Python311\Lib\subprocess.py", line 1661, in send_signal
    os.kill(self.pid, signal.CTRL_BREAK_EVENT)
SystemError: <built-in function kill> returned a result with an exception set

Below is the standalone script to reproduce this issue with pythonw

import logging
import shlex
import signal
import subprocess
import time

import psutil

logging.basicConfig(
    filename="pyw_log.txt",
    filemode="a",
    format="%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s",
    datefmt="%Y-%m-%d:%H:%M:%S",
    level=logging.DEBUG,
)
logger = logging.getLogger(__name__)

logger.debug(f"===================================================================")


def process_tree(parent_pid):
    parent_process = psutil.Process(parent_pid)
    for i, child_process in enumerate(parent_process.children(recursive=True)):
        logger.debug(f"Child PID: {child_process.pid}, cmd: {child_process.cmdline()}")
        print(f"Child PID: {child_process.pid}, cmd: {child_process.cmdline()}")


try:
    startup_info = subprocess.STARTUPINFO()
    startup_info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    creation_flags = subprocess.CREATE_NEW_PROCESS_GROUP

    cmd_line = "netstat"
    print(cmd_line)
    logger.info(cmd_line)

    cmd_line = shlex.split(cmd_line)
    logger.debug(cmd_line)

    with open("process_log.txt", mode="w", encoding="UTF-8") as file:
        process = subprocess.Popen(
            cmd_line,
            stdout=file,
            stderr=file,
            stdin=subprocess.DEVNULL,
            # shell=True,  # no effect
            encoding="UTF-8",
            startupinfo=startup_info,
            creationflags=creation_flags,
        )
        print(process.pid)
        logger.info(process.pid)

        time.sleep(2)

        process_tree(process.pid)
        process.send_signal(signal.CTRL_BREAK_EVENT)

        out, err = process.communicate()
        logger.debug(f"Ret code: {process.returncode}")
        logger.debug(f"Out: {out}")
        logger.debug(f"Error: {err}")
        print(f"Out: {out}")
except Exception:
    logging.exception("")
    # raise
finally:
    process.kill()  # This one doesn't raise any exception when the process already died
    logger.debug("Process killed/died automatically")
0

There are 0 best solutions below