|
"""Use a Windows event to interrupt a child process like SIGINT. |
|
|
|
The child needs to explicitly listen for this - see |
|
ipykernel.parentpoller.ParentPollerWindows for a Python implementation. |
|
""" |
|
import ctypes |
|
from typing import Any |
|
|
|
|
|
def create_interrupt_event() -> Any: |
|
"""Create an interrupt event handle. |
|
|
|
The parent process should call this to create the |
|
interrupt event that is passed to the child process. It should store |
|
this handle and use it with ``send_interrupt`` to interrupt the child |
|
process. |
|
""" |
|
|
|
|
|
|
|
|
|
class SECURITY_ATTRIBUTES(ctypes.Structure): |
|
_fields_ = [ |
|
("nLength", ctypes.c_int), |
|
("lpSecurityDescriptor", ctypes.c_void_p), |
|
("bInheritHandle", ctypes.c_int), |
|
] |
|
|
|
sa = SECURITY_ATTRIBUTES() |
|
sa_p = ctypes.pointer(sa) |
|
sa.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES) |
|
sa.lpSecurityDescriptor = 0 |
|
sa.bInheritHandle = 1 |
|
|
|
return ctypes.windll.kernel32.CreateEventA( |
|
sa_p, |
|
False, |
|
False, |
|
"", |
|
) |
|
|
|
|
|
def send_interrupt(interrupt_handle: Any) -> None: |
|
"""Sends an interrupt event using the specified handle.""" |
|
ctypes.windll.kernel32.SetEvent(interrupt_handle) |
|
|