Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"failed to write to console" exception on Windows when writing to NUL-redirected file handle #2080

Closed
nickhutchinson opened this issue Dec 30, 2020 · 4 comments

Comments

@nickhutchinson
Copy link
Contributor

nickhutchinson commented Dec 30, 2020

On Windows, fmtlib can throw an exception when writing to a FILE* handle that's been redirected to the NUL device (Windows' equivalent of /dev/null).

This occurs when fmtlib is in unicode mode -- e.g. you're building with Visual Studio with FMT_UNICODE defined, or with clang -- because the WriteConsoleW() function fmtlib calls will fail if it's passed a file handle that's not actually a console. Unfortunately on Windows _isatty() is not a robust test for determining if a given fd is a console.

I would suggest calling GetConsoleMode() instead (or perhaps in addition to the _isatty check, depending on your level of paranoia!). This is how the UCRT itself determine whether it should call WriteConsoleW -- if you have the Windows SDK installed, you can check the source at Source/<version>/ucrt/lowio/write.cpp.

To repro:

#include <cstdio>

#define FMT_UNICODE 1
#include <fmt/core.h>

int main() {
  fmt::print("crash!\n"); // throws exception if stdout has been redirected to NUL

  FILE* fp = std::fopen("NUL", "w");
  fmt::print(fp, "crash!\n"); // throws exception
}
@vitaut
Copy link
Contributor

vitaut commented Dec 30, 2020

Thanks for reporting but I wasn't able to repro the issue:

#define FMT_UNICODE 1
#define FMT_HEADER_ONLY
#include <fmt/format.h>

int main() {
  fmt::print("crash!\n");
}
>cl test.cc /I include /EHsc
>test > NUL

doesn't throw an exception and prints nothing. Same with fopen instead of redirection.

What Windows version, compiler and compiler options do you use?

@nickhutchinson
Copy link
Contributor Author

nickhutchinson commented Dec 30, 2020

Thanks for reporting but I wasn't able to repro the issue:

#define FMT_UNICODE 1
#define FMT_HEADER_ONLY
#include <fmt/format.h>

int main() {
  fmt::print("crash!\n");
}
>cl test.cc /I include /EHsc
>test > NUL

doesn't throw an exception and prints nothing. Same with fopen instead of redirection.

Apologies for the incomplete repro steps. Are you sure the process in your example isn't throwing an exception? I get an exception with the source and compile flags you list. I'd double-check the process' exit status (echo %ERRORLEVEL%) -- when a process calls abort() (i.e. because of the unhandled exception), you should get an exit code of -1073740791 a.k.a 0xC0000409 / STATUS_FAIL_FAST_EXCEPTION. (Make sure you're not using git-bash or similar, as it can't represent the full range of Win32 process exit codes.)

You could also add /MDd to the compile line to build against the debug C runtime -- this will by default raise a UI dialog when abort() is called, so it'll be more visible.

What Windows version, compiler and compiler options do you use?

Windows 10 x64, version 20H2

> cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29335 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]

@vitaut
Copy link
Contributor

vitaut commented Dec 30, 2020

I can repro with /MDd, thanks.

@vitaut
Copy link
Contributor

vitaut commented Dec 30, 2020

Fixed in 9ec5592. Thanks again for catching this.

@vitaut vitaut closed this as completed Dec 30, 2020
rvogg added a commit to jhnc-oss/ccache that referenced this issue Oct 6, 2021
This fixes some bugs when piping to /dev/null.
(see fmtlib/fmt#2080)
rvogg added a commit to jhnc-oss/ccache that referenced this issue Oct 26, 2021
This fixes some bugs when piping to /dev/null.
(see fmtlib/fmt#2080)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants