Eryk Sun <eryk...@gmail.com> added the comment:

> It sounds like we should probably revert to the middle ground, and 
> skip _raising the error_ if _Py_set_inheritable for files of type
> FILE_TYPE_CHAR.

The problem is just console pseudohandles in Windows 7 and earlier.  Maybe it 
should just check for this case before calling SetHandleInformation. For 
example:

    /* This check can be removed once support for Windows 7 ends. */
    #define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && 
\
            GetFileType(handle) == FILE_TYPE_CHAR)

    if (!CONSOLE_PSEUDOHANDLE(handle) &&
        !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
        if (raise)
            PyErr_SetFromWindowsErr(0);
        return -1;
    }

We have similar Python code in subprocess Popen._filter_handle_list, which 
filters out console pseudohandles because they don't work with 
PROC_THREAD_ATTRIBUTE_HANDLE_LIST.

A similar check could be added to os_set_handle_inheritable_impl in 
Modules/posixmodule.c.

> As Victor pointed out, the docs already call out the special case in 
> Windows. 

For os.dup it says

    On Windows, when duplicating a standard stream (0: stdin, 1: 
    stdout, 2: stderr), the new file descriptor is inheritable.

The standard handles aren't relevant.

Also, under "inheritance of file descriptors", it says:

    On Windows, non-inheritable handles and file descriptors are closed 
    in child processes, except for standard streams (file descriptors 0,
    1 and 2: stdin, stdout and stderr), which are always inherited.

The standard handles aren't always inherited. If bInheritHandles is TRUE (i.e. 
close_fds=False), a standard handle has to be iheritable for it to be 
inherited. 

For example, in Windows 10, make stderr (a ConDrv console handle) 
non-inheritable and create a child process with close_fds=False:

    >>> os.set_handle_inheritable(msvcrt.get_osfhandle(2), False)
    >>> cmd = 'import sys; print(sys.stderr)'
    >>> subprocess.call(f'python.exe -c "{cmd}"', close_fds=False)
    None
    0

In Windows 7 and earlier, it seems that inheritable console pseudohandles are 
always inherited, regardless of bInheritHandles -- as long as the child process 
attaches to the parent's console. SetHandleInformation isn't supported for 
console pseudohandles, but the inheritable flag is still set or cleared when a 
console pseudohandle is created via CreateConsoleScreenBuffer, CreateFileW 
(routed to OpenConsoleW), and DuplicateHandle (routed to 
DuplicateConsoleHandle).

It's worth mentioning that the system sometimes duplicates (not inherits) 
standard handles to a child process. A simple example in Windows 10 would be 
subprocess.call('python.exe'). 

All of the follow requirements must be satisfied for CreateProcessW to 
duplicate a standard handle to a child:

* it's not a console pseudohandle (e.g. it's a ConDrv console handle in 
  Windows 8+, or handle for the NUL device, a pipe, or disk file)
* the target executable is a console application (e.g. python.exe, not 
  pythonw.exe)
* handle inheritance is disabled (i.e. bInheritHandles is FALSE)
* the startup-info standard handles aren't used (i.e. 
  STARTF_USESTDHANDLES isn't set)
* the call isn't flagged to execute without a console or to allocate a
  new console (i.e. no DETACHED_PROCESS, CREATE_NEW_CONSOLE, or 
  CREATE_NO_WINDOW)

In this case, CreateProcessW also has to update the handle value in the child 
since generally the duplicate has a new value. With inheritance, in contrast, 
the handle value is the same in the parent and child.

----------

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

Reply via email to