eryksun added the comment:
The default (and standards-violating) behavior of the Windows CRT is to kill
the process for a bad file descriptor, instead of just setting errno to EBADF.
To work around this PyOS_StdioReadline needs to to check _Py_Verify_fd before
calling fflush or writing to stderr. A similar check was added to my_fgets in
3.2.5 (see issue 14433), but it wasn't backported to Python 2.
The REPL in 3.x still uses C FILE streams, so this problem absolutely affects
3.x. (Except 3.5.0a2 and 3.5.0a3 have a hack that hides the problem. The hack
has since been removed, so the problem has returned out of hiding in recent
builds.) Previously I omitted the stack trace for brevity because it's
virtually identical to 2.7, but here it is as justification for adding 3.x back
to the issue's versions field.
C:\Program Files\Python34>cdb -xi ld python
Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: python
Symbol search path is:
symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(1184.11f0): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`76e8cb70 cc int 3
0:000> bp ntdll!NtTerminateProcess
0:000> g
Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:16:31) [MSC v.1600 64
bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.close(2)
Breakpoint 0 hit
ntdll!NtTerminateProcess:
00000000`76e31570 4c8bd1 mov r10,rcx
0:000> kc
Call Site
ntdll!NtTerminateProcess
KERNELBASE!TerminateProcess
MSVCR100!invalid_parameter
MSVCR100!invalid_parameter_noinfo
MSVCR100!write
MSVCR100!flush
MSVCR100!fflush_nolock
MSVCR100!fflush
python34!PyOS_StdioReadline
python34!PyOS_Readline
python34!tok_nextc
python34!tok_get
python34!PyTokenizer_Get
python34!parsetok
python34!PyParser_ParseFileObject
python34!PyParser_ASTFromFileObject
python34!PyRun_InteractiveOneObject
python34!PyRun_InteractiveLoopFlags
python34!PyRun_AnyFileExFlags
python34!run_file
python34!Py_Main
python!__tmainCRTStartup
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
Additionally, here's a trace that demonstrates the silent handler hack that's
present in 3.5.0a2:
C:\Program Files\Python35>cdb -xi ld python
Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: python
Symbol search path is:
symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(1040.113c): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`76e8cb70 cc int 3
0:000> bp ucrtbase!set_thread_local_invalid_parameter_handler
0:000> bp python35!_silent_invalid_parameter_handler
0:000> g
With this hack in place, new_threadstate unconditionally sets the invalid
parameter handler to _silent_invalid_parameter_handler (again, this has since
been removed):
Breakpoint 0 hit
ucrtbase!set_thread_local_invalid_parameter_handler:
000007fe`e47c8740 4053 push rbx
0:000> kc
Call Site
ucrtbase!set_thread_local_invalid_parameter_handler
python35!new_threadstate
python35!_Py_InitializeEx_Private
python35!Py_Main
python!__scrt_common_main_seh
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
0:000> g
Python 3.5.0a2 (v3.5.0a2:0337bd7ebcb6, Mar 8 2015, 07:17:31) [MSC v.1900
64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.close(2)
Breakpoint 1 hit
python35!_silent_invalid_parameter_handler:
00000000`5f6e9d60 c20000 ret 0
0:000> kc
Call Site
python35!_silent_invalid_parameter_handler
ucrtbase!invalid_parameter
ucrtbase!write
ucrtbase!_acrt_stdio_flush_nolock
ucrtbase!fflush_nolock
ucrtbase!fflush
python35!PyOS_StdioReadline
python35!PyOS_Readline
python35!tok_nextc
python35!tok_get
python35!parsetok
python35!PyParser_ASTFromFileObject
python35!PyRun_InteractiveOneObject
python35!PyRun_InteractiveLoopFlags
python35!PyRun_AnyFileExFlags
python35!run_file
python35!Py_Main
python!__scrt_common_main_seh
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
I think for 3.5 the affected code needs to be bracketed by
_Py_BEGIN_SUPPRESS_IPH and _Py_END_SUPPRESS_IPH. This works on my personal
build. See issue 23524 for more details regarding the new macros.
----------
versions: +Python 3.4, Python 3.5
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue19050>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com