Eryk Sun added the comment:

Background Discussion

The Windows 10 console uses the condrv.sys device driver, which is set up as 
follows in the NT namespace:

    C:\>odir \ -r -n con;con*$;cond*
    Directory of \

    Device
        ConDrv <Device>
    Driver
        condrv <Driver>
    GLOBAL??
        CON -> \Device\ConDrv\Console
        CONIN$ -> \Device\ConDrv\CurrentIn
        CONOUT$ -> \Device\ConDrv\CurrentOut

Previously the base console API used an NT LPC port to communicate with the 
attached console process (i.e. an instance of conhost.exe). There wasn't a real 
console device. Instead, opening "CON", "CONIN$", or "CONOUT$" was special 
cased to call OpenConsoleW (undocumented). 

With the new console device driver, opening the DOS "CON" device gets 
translated to the NT path "\Device\ConDrv\Console", i.e. it opens the file 
named "Console" on the ConDrv device. 

Opening the Console file returns a handle for a regular kernel File object. To 
that end, you may have noticed that console handles in Windows 10 are no longer 
tagged for routing by setting the lower two bits (e.g. 3, 7, 11, etc). For 
example:

    >>> kernel32.GetStdHandle(STD_INPUT_HANDLE)
    32
    >>> kernel32.DebugBreak()
    (e1c.e20): Break instruction exception - code 80000003 (first chance)
    KERNELBASE!DebugBreak+0x2:
    00007ffa`60280262 cc              int     3

    0:000> !handle 32
    Handle 32
      Type          File

Previously, all operations on console handles were internally routed to special 
console functions, such as ReadFile => ReadConsoleA. Thus with the old 
LPC-based console, a ReadFile basically has the behavior of ReadConsoleA (with 
the addition of special casing input lines that start with Ctrl+Z). 

The new design scraps a lot of the special-cased code. For example, reading 
from a console handle in Windows 10 uses a regular NtReadFile system call. So 
the error it sets, if any at all, depends on translating the NTSTATUS code 
that's returned by NtReadFile. Let's see what status the console sets here:

    C:\Temp>cdb -xi ld python ccbug.py

    [...]

    ntdll!LdrpDoDebuggerBreak+0x30:
    00007ffb`170de260 cc              int     3
    0:000> g
    3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25)
    [MSC v.1900 64 bit (AMD64)]

    calling DebugBreak...
    (8d0.62c): Break instruction exception - code 80000003 (first chance)
    KERNELBASE!DebugBreak+0x2:
    00007ffb`13f40262 cc              int     3
    0:000> bp ntdll!NtReadFile
    0:000> g
    Breakpoint 0 hit
    ntdll!NtReadFile:
    00007ffb`170b35d0 4c8bd1          mov     r10,rcx
    0:000> pt
    ntdll!NtReadFile+0xa:
    00007ffb`170b35da c3              ret
    0:000> r rax
    rax=0000000000000101

The console weirdly returns a success code, STATUS_ALERTED (0x101, "the delay 
completed because the thread was alerted"), which is why ReadFile doesn't set 
an error. STATUS_ALERTED is normally returned when an NT wait function gets 
alerted by NtAlertThread (note that this is not the same as getting alerted by 
an asynchronous procedure call). For example:
    
    tid = threading.get_ident()
    h = kernel32.OpenThread(MAXIMUM_ALLOWED, 0, tid)
    t = threading.Timer(5, ntdll.NtAlertThread, (h,))
    delay = LARGE_INTEGER(10 * -10**7) # 10 seconds
    t.start()
    r = ntdll.NtDelayExecution(True, byref(delay))

    >>> hex(r)
    '0x101'

NtAlertThread is rarely used because WinAPI wait functions (e.g. SleepEx) 
automatically restart a wait when the underlying NT wait returns 
STATUS_ALERTED. 

The ReadConsole implementation has always translated STATUS_ALERTED to 
ERROR_OPERATION_ABORTED. This still exists in the Windows 10 implementation of 
ReadConsole. However, the correct error status for this case is 
STATUS_CANCELLED (0xC0000120, "the I/O request was cancelled"): 

    >>> ntdll.RtlNtStatusToDosError(0xC0000120)
    995

Whoever reimplemented the console IPC using a device driver should have updated 
the console to return STATUS_CANCELLED when an I/O operation is interrupted by 
Ctrl+C or Ctrl+Break. Then nothing would need to be special cased.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue18597>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to