You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Windows] suggestion for os.kill(pid,CTRL_C_EVENT) in tests #55570
26,27d25
< elif sig == signal.SIGINT:
< pass
34,35d31
< def ctrl_handler_int(sig, obj):
< sys.exit(1)
40d35
< NULL = ctypes.POINTER(ctypes.c_int)()
43,53d37
< # Calling this with NULL and FALSE causes the calling process to
< # handle CTRL+C, rather than ignore it. This property isn't inherited
< # by subprocesses, if it's created with CREATE_NEW_PROCESS_GROUP flag
< SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int), wintypes.B
OOL)
< if not SetConsoleCtrlHandler(NULL, 0):
< print("Unable to restore SetConsoleCtrlHandler")
< exit(-1)
<
< signal.signal(signal.SIGINT, ctrl_handler_int)
<
< SetConsoleCtrlHandler.argtypes = (HandlerRoutine, wintypes.BOOL)
57a42
And on my machine (win2003 32bit):
...
test_CTRL_BREAK_EVENT (main.Win32KillTests) ... ok
test_CTRL_C_EVENT (main.Win32KillTests) ... ok
test_kill_int (main.Win32KillTests) ... ok
test_kill_sigterm (main.Win32KillTests) ... ok
----------------------------------------------------------------------
Ran 61 tests in 2.344s
Oh, if the process is able to handle CTRL+c on Windows, it means that faulthandler.register() could be used on Windows. While developing the faulthandler module, I tried all signals but I was only able to handle SIGSEGV, SIGABRT, SIGBUS and SIGILL on Windows. And all of these signals are reserved to faulthandler.enable() function. So faulthandler.register() is just not compiled on Windows.
If SetConsoleCtrlHandler() is really useful, we should maybe add something to the signal module to give access to this function.
test test_os failed -- Traceback (most recent call last):
File "D:\cygwin\home\db3l\buildarea\3.x.bolen-windows\build\lib\test\test_os.py", line 1177, in test_CTRL_BREAK_EVENTself._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
File "D:\cygwin\home\db3l\buildarea\3.x.bolen-windows\build\lib\test\test_os.py", line 1155, in _kill_with_eventself.fail("subprocess did not stop on {}".format(name))
AssertionError: subprocess did not stop on CTRL_BREAK_EVENT
test_CTRL_C_EVENT can be removed from Lib/test/test_os.py. It's of no practical consequence. Ctrl+Break is always enabled in the child process, so test_CTRL_BREAK_EVENT should remain.
When using CREATE_NEW_PROCESS_GROUP, the child process is started with Ctrl+C disabled. Whether or not Ctrl+C is enabled in the parent process is irrelevant.
An example that shows the intent of this creation flag is the /B (background) option of the cmd shell's "start" command. Ctrl+C from the user shouldn't interrupt such programs, so "start /B" uses the CREATE_NEW_PROCESS_GROUP creation flag. You can still kill the process with Ctrl+Break, assuming it hasn't installed a control handler that ignores CTRL_BREAK_EVENT instead of chaining to the default handler.
For example:
C:\>start /b /w py -3
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37)
[MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import time
>>> import signal
>>> import ctypes
>>>
>>> _ = signal.signal(signal.SIGINT, lambda *a: print('^C'))
>>> _ = signal.signal(signal.SIGBREAK, lambda *a: print('^BREAK'))
>>>
>>> def test_ctrl_event(event):
... os.kill(os.getpid(), event)
... time.sleep(1)
...
>>> test_ctrl_event(signal.CTRL_BREAK_EVENT) # works
^BREAK
>>> test_ctrl_event(signal.CTRL_C_EVENT) # nothing
As this issue notes, the child process can use ctypes to manually enable Ctrl+C events for the current process:
>>> ctypes.windll.kernel32.SetConsoleCtrlHandler(None, 0)
1
>>> test_ctrl_event(signal.CTRL_C_EVENT) # works
^C
But this is contrived. You rarely have such control over the child process unless it's your own code, in which case there are far better IPC mechanisms available than to rely on the console host process (conhost.exe) as th arbiter of communication.
changed the title [-]suggestion for os.kill(pid,CTRL_C_EVENT) in tests[/-][+][Windows] suggestion for os.kill(pid,CTRL_C_EVENT) in tests[/+]on Mar 8, 2021
Activity
iigor commentedon Mar 1, 2011
Hello!
I see some 'skip' in test_os.py
I think, problem with calling SetConsoleCtrlHandler(NULL,0) in parent process, rather in child. If call SetConsoleCtrlHandler(NULL, 0).
Calling SetConsoleCtrlHandler(ctrl_handler, 1) is not enough. Need first call SetConsoleCtrlHandler(NULL, 0).
My patch for this test fixture: (may be, not so good, but it works)
H:\usr\python27\Lib\test>diff win_console_handler.py win_console_handler.py_orig
26,27d25
< elif sig == signal.SIGINT:
< pass
34,35d31
< def ctrl_handler_int(sig, obj):
< sys.exit(1)
40d35
< NULL = ctypes.POINTER(ctypes.c_int)()
43,53d37
< # Calling this with NULL and FALSE causes the calling process to
< # handle CTRL+C, rather than ignore it. This property isn't inherited
< # by subprocesses, if it's created with CREATE_NEW_PROCESS_GROUP flag
< SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int), wintypes.B
OOL)
< if not SetConsoleCtrlHandler(NULL, 0):
< print("Unable to restore SetConsoleCtrlHandler")
< exit(-1)
<
< signal.signal(signal.SIGINT, ctrl_handler_int)
<
< SetConsoleCtrlHandler.argtypes = (HandlerRoutine, wintypes.BOOL)
57a42
And on my machine (win2003 32bit):
...
test_CTRL_BREAK_EVENT (main.Win32KillTests) ... ok
test_CTRL_C_EVENT (main.Win32KillTests) ... ok
test_kill_int (main.Win32KillTests) ... ok
test_kill_sigterm (main.Win32KillTests) ... ok
----------------------------------------------------------------------
Ran 61 tests in 2.344s
OK
[-]suggestion for os.kill(pid,CTRL_C_EVENT)[/-][+]suggestion for os.kill(pid,CTRL_C_EVENT) in tests[/+]vstinner commentedon May 1, 2011
Oh, if the process is able to handle CTRL+c on Windows, it means that faulthandler.register() could be used on Windows. While developing the faulthandler module, I tried all signals but I was only able to handle SIGSEGV, SIGABRT, SIGBUS and SIGILL on Windows. And all of these signals are reserved to faulthandler.enable() function. So faulthandler.register() is just not compiled on Windows.
If SetConsoleCtrlHandler() is really useful, we should maybe add something to the signal module to give access to this function.
vstinner commentedon May 2, 2011
http://www.python.org/dev/buildbot/all/builders/x86%20XP-4%203.x/builds/4483/steps/test/logs/stdio
----------
gpshead commentedon Jul 10, 2014
(un-cc'ing myself as I can't deal with Windows)
eryksun commentedon Dec 5, 2015
test_CTRL_C_EVENT can be removed from Lib/test/test_os.py. It's of no practical consequence. Ctrl+Break is always enabled in the child process, so test_CTRL_BREAK_EVENT should remain.
When using CREATE_NEW_PROCESS_GROUP, the child process is started with Ctrl+C disabled. Whether or not Ctrl+C is enabled in the parent process is irrelevant.
An example that shows the intent of this creation flag is the /B (background) option of the cmd shell's "start" command. Ctrl+C from the user shouldn't interrupt such programs, so "start /B" uses the CREATE_NEW_PROCESS_GROUP creation flag. You can still kill the process with Ctrl+Break, assuming it hasn't installed a control handler that ignores CTRL_BREAK_EVENT instead of chaining to the default handler.
For example:
C:\>start /b /w py -3 Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> import time >>> import signal >>> import ctypes >>> >>> _ = signal.signal(signal.SIGINT, lambda *a: print('^C')) >>> _ = signal.signal(signal.SIGBREAK, lambda *a: print('^BREAK')) >>> >>> def test_ctrl_event(event): ... os.kill(os.getpid(), event) ... time.sleep(1) ... >>> test_ctrl_event(signal.CTRL_BREAK_EVENT) # works ^BREAK >>> test_ctrl_event(signal.CTRL_C_EVENT) # nothingAs this issue notes, the child process can use ctypes to manually enable Ctrl+C events for the current process:
>>> ctypes.windll.kernel32.SetConsoleCtrlHandler(None, 0) 1 >>> test_ctrl_event(signal.CTRL_C_EVENT) # works ^CBut this is contrived. You rarely have such control over the child process unless it's your own code, in which case there are far better IPC mechanisms available than to rely on the console host process (conhost.exe) as th arbiter of communication.
[-]suggestion for os.kill(pid,CTRL_C_EVENT) in tests[/-][+][Windows] suggestion for os.kill(pid,CTRL_C_EVENT) in tests[/+]