Hi all,

recently I’ve been playing around with sending and catching signals on
Windows. I finally found out how to send and catch a BREAK event.

With Python 2.7(.2), I only need os.kill(pid, signal.CTRL_C_EVENT) and
signal.signal(signal.SIGBREAK, handler). Alternatively, I can use GenerateConsoleCtrlEvent and SetConsoleCtrlHandler via ctypes.

However, the former does not work with Python 3.3 (64bit) and the latter always raises a KeyError in Python’s threading module.

My question is: Should signal.signal(signal.SIGBREAK, handler) work under Python 3.3? If so, what am I doing wrong? Why raises the
ctypes-variant an error while the signal-variant doesn’t?

Below is a minimal example illustrating my problem:

# sigterm_min.py
import os
import signal
import subprocess
import sys
import time


WIN = (sys.platform == 'win32')
kwargs = {}
if WIN:
    kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP


def parent():
proc = subprocess.Popen(['python', 'sigterm_min.py', 'child'], **kwargs)
    time.sleep(1)

    if WIN:
        # This works on Python 2.7 and 3.3:
        os.kill(proc.pid, signal.CTRL_BREAK_EVENT)

        # Alternative (ugly) way:
        # import ctypes
        # ctypes.windll.kernel32.GenerateConsoleCtrlEvent(
        #         signal.CTRL_BREAK_EVENT, proc.pid)
    else:
        proc.terminate()

    print('parent waiting for child')
    proc.wait()
    print('parent terminating')


def child():
    def handler(signum, frame=None):
        print('child terminating')
        sys.exit(0)

    if WIN:
        # This only works on Python 2.7, but not on 3.3:
        signal.signal(signal.SIGBREAK, handler)

        # (Ugly) alternative that works on both Python 2.7 and 3.3,
        # but raises a KeyError in threading.py:
        # import ctypes
        # handler = ctypes.WINFUNCTYPE(ctypes.c_int,
        #                              ctypes.c_uint)(handler)
        # ctypes.windll.kernel32.SetConsoleCtrlHandler(handler, True)
    else:
        signal.signal(signal.SIGTERM, handler)

    time.sleep(10)


if __name__ == '__main__':
    if len(sys.argv) == 1:
        parent()
    elif sys.argv[1] == 'child':
        child()
# EOF

Cheers,
Stefan
_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to