Eryk Sun <eryk...@gmail.com> 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 <rep...@bugs.python.org>
<https://bugs.python.org/issue35935>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to