Skip to content

On Windows is_terminal always returns false if the handle is not opened with read access #130974

Open
@ChrisDenton

Description

@ChrisDenton

Minimal example:

use std::io::IsTerminal;

fn main() {
    let conout = r"\\.\CONOUT$";
    let stdout = std::fs::File::options().write(true).open(conout).unwrap();
    assert!(stdout.is_terminal());
}

This is because we use GetConsoleMode to determine if a handle is a console handle or not and the docs for GetConsoleMode state:

The handle must have the GENERIC_READ access right.

We could check the error of GetConsoleMode and, if it's ERROR_ACCESS_DENIED, then use GetFileType to see if it returns FILE_TYPE_CHAR. We can't use GetFileType alone because, for example, the NUL device claims to be a character device.

EDIT: Maybe simpler, we could check if GetConsoleMode errors with ERROR_INVALID_HANDLE though I'm not 100% sure it'll always return that for non-console handles.

Alternatively we could just close this issue and say this is not our problem. Most applications and runtimes don't do anything special here and simply treat it as a non-console handle.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`C-bugCategory: This is a bug.O-windowsOperating system: WindowsT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions