Skip to content

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

Open
@ChrisDenton

Description

@ChrisDenton
Member

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.

Activity

added
A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`
C-bugCategory: This is a bug.
O-windowsOperating system: Windows
T-libsRelevant to the library team, which will review and decide on the PR/issue.
on Sep 28, 2024
added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Sep 28, 2024
removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Sep 28, 2024
ChrisDenton

ChrisDenton commented on Sep 28, 2024

@ChrisDenton
MemberAuthor

Ideally we could use NtQueryVolumeInformationFile with FileFsDeviceInformation to get the device type. This doesn't have the problem of GetFileType and we also don't need any complex inference. However, I hesitate to suggest this as we do try to use win32 functions unless there's no alternative.

estebank

estebank commented on Oct 2, 2024

@estebank
Contributor

Alternatively we could just close this issue and say this is not our problem.

We could also try and lint against calling is_terminal on a read-only handle. But I'd prefer using the alternative proposed platform APIs instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

        Participants

        @estebank@ChrisDenton@rustbot

        Issue actions

          On Windows `is_terminal` always returns `false` if the handle is not opened with read access · Issue #130974 · rust-lang/rust