osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

if STREAM.isatty():


On 8/30/19, Chris Angelico <rosuav at gmail.com> wrote:
> On Sat, Aug 31, 2019 at 5:40 AM Eryk Sun <eryksun at gmail.com> wrote:
>
>> Or simply run python.exe from another console process that keeps the
>> console alive (it's reference counted), which is typically cmd.exe or
>> powershell.exe.
>
> Not sure what you mean by "reference counted"

In Windows 8+, a process attaches to a console by opening
"\Device\ConDrv\Connect" as a connection to an instance of the console
host process, conhost.exe. This handle is stored internally as
"ConsoleHandle" (in its PEB->ProcessParameters). The console API uses
this handle for functions that don't operate on a stream, such as
GetConsoleTitle.

Every open instance of this "Connect" file that connects a process to
a console is a reference on the console that keeps it alive. And every
handle for a kernel File object is a counted reference on the object.
Thus if we call DuplicateHandle to duplicate the connection handle to
another process that's not technically 'attached' to the console, then
even if we close all processes attached to the console, the console
will not be destroyed until the duplicate handle for the connection is
closed.

Other console files that have this property are "CON" (i.e.
"\Device\ConDrv\Console"), "CONIN$" (i.e. "\Device\ConDrv\CurrentIn")
and "CONOUT$" (i.e. "\Device\ConDrv\CurrentOut"). When opened, these
files reference the active input or output stream of the currently
attached console, and they keep the console alive. However, they only
work for I/O when we're attached to the referenced console, so this
property isn't really useful. Attaching to a console via WINAPI
AttachConsole requires the PID of a process that's already attached to
the console (and thus keeping it alive).

On the other hand, by default a console process starts with its
StandardInput handle set to a generic console input file (i.e.
"\Device\ConDrv\Input") and its StandardOutput and StandardError
handles set to a generic console output file (i.e.
"\Device\ConDrv\Output"). These generic files work with any console
connection, and they do not keep a console alive.

The implementation details of the console are completely different
prior to Windows 8, and not all behaviors are consistent with the
above description. But Windows 7 is almost at end of life.

> Of course, most of us use a shell that's a tad more powerful than
> cmd.exe, but the effect is the same regardless.

Yes, CMD is not a great shell, and PowerShell is tedious (IMO). We can
use bash.exe from MSYS2 or Git instead. But stick to the normal
console interface (i.e. run bash.exe directly), or use winpty if you
need to run Windows Python. The MSYS2 terminal interface (mintty) is
based on named pipes. Its build of Python special cases these pipes,
but they're just pipes to the Windows build, so isatty() is false and
it defaults to full buffering. Also, the REPL of the Windows build
depends on the system console for line editing and history, so even if
we force interactive mode via `python -i`, the UI is horrible without
a console.