Eryk Sun <[email protected]> added the comment:
Alexander, I wrote the above sample function to be slotted directly into the
existing design based on the SIGINT event. I wasn't looking to rewrite
everything using user-mode APCs and alertable waits. A change like that could
have ramifications for applications that already use alertable waits, depending
on how resiliently they're designed.
> Originally, Windows devised an APC mechanism to simulate asynchronous
> delivery of Posix signal to threads.
IIRC, Iterix (i.e. SUA -- replaced nowadays by WSL) used Asynchronous Procedure
Calls (APCs) to implement Unix signals. But APCs certainly weren't devised
solely for the purpose of the providing signals in the POSIX subsystem. They're
an evolution of Asynchronous System Traps (ASTs) in DEC VMS. (The lead designer
of NT and most of the development team originally designed and implemented VMS
at DEC. They began working at Microsoft to design the NT system and OS/2,
Win32, and POSIX subsystems starting in late 1988.) Kernel-mode and user-mode
APCs are fundamental and critical to NT (e.g. thread termination uses an APC),
and particularly the I/O system, which uses a special kernel-mode APC for I/O
request completion. (An I/O request is often serviced in an arbitrary thread
context. Buffered I/O completion has to be queued back to the calling thread in
order to copy from a system buffer to the user buffer.)
> Those APCs are invoked during alertable wait functions. Delivery
> of an APS also aborts the wait with WAIT_IO_COMPLETION return code.
WAIT_IO_COMPLETION is the same as STATUS_USER_APC, because I/O completion
routines are queued as user-mode APCs (e.g. by ReadFileEx). Using the name
"WAIT_IO_COMPLETION" clarifies the intent in this case. In general, I prefer
"STATUS_USER_APC".
> An APC queue can be processed at any time by calling an alertable
> wait function with zero timeout, for example SleepEx(0, TRUE).
The user-mode APC queue can also be pumped by calling the NtTestAlert() system
function. For example:
import ctypes
ntdll = ctypes.WinDLL('ntdll')
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
@ctypes.WINFUNCTYPE(None, ctypes.c_void_p)
def apc(p):
print('spam APC')
hthread = ctypes.c_void_p(-2)
kernel32.QueueUserAPC(apc, hthread, None)
>>> ntdll.NtTestAlert(hthread)
spam APC
0
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue35935>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com