This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients eryksun, jpe, steve.dower, tim.golden, zach.ware
Date 2015-04-15.17:41:43
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1429119703.99.0.400384848458.issue23948@psf.upfronthosting.co.za>
In-reply-to
Content
> it only works if the the target process id is 0 and then it 
> generates the signal in all processes that share the console.

You can target a process group, which is a subset of the console's attached processes. That's why the console host, conhost.exe, routes dispatching the event through the session CSRSS.EXE, which handles bookkeeping of Windows processes and threads, including groups.

CSRSS creates a thread in each target, which starts at kernel32!CtrlRoutine. If a process is being debugged this routine raises a DBG_CONTROL_C or DBG_CONTROL_BREAK exception. Next it calls the registered handlers. The default handler, if called, exits the process with the exit code set to STATUS_CONTROL_C_EXIT (0xC000013A):

    0:000> u kernel32!DefaultHandler l3
    kernel32!DefaultHandler:
    00000000`76f31290 4883ec28        sub     rsp,28h
    00000000`76f31294 b93a0100c0      mov     ecx,0C000013Ah
    00000000`76f31299 ff15e1bb0500    call    qword ptr
                                              [kernel32!
                                               _imp_RtlExitUserProcess 
                                               (00000000`76f8ce80)]

Example:

    import os
    import sys
    import signal
    import subprocess
    import threading

    STATUS_CONTROL_C_EXIT = 0xC000013A

    p = subprocess.Popen([sys.executable, '-i'],
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
    p.stderr.read(1) # poor man's WaitForInputIdle

    os.kill(p.pid, signal.CTRL_BREAK_EVENT)
    watchdog = threading.Timer(5, p.terminate)
    watchdog.start()
    exitcode = p.wait()
    watchdog.cancel()

    if exitcode < 0:
        exitcode += 2 ** 32
    assert exitcode == STATUS_CONTROL_C_EXIT
History
Date User Action Args
2015-04-15 17:41:44eryksunsetrecipients: + eryksun, jpe, tim.golden, zach.ware, steve.dower
2015-04-15 17:41:43eryksunsetmessageid: <1429119703.99.0.400384848458.issue23948@psf.upfronthosting.co.za>
2015-04-15 17:41:43eryksunlinkissue23948 messages
2015-04-15 17:41:43eryksuncreate