From fb3e7825f35ba165a6785fba5e8c5eddbc6aa3f5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 23 May 2025 09:03:03 -0400 Subject: [PATCH] StdIo: Restore Windows Console I/O modes on exit The Windows documentation [1] states: > command-line applications should capture the initial console > mode at startup and attempt to restore it when exiting We set `ENABLE_VIRTUAL_TERMINAL_{INPUT,PROCESSING}` modes since commit d6a1ff59f1 (StdIo: Provide metadata about stdin, stdout, stderr streams, 2025-05-06). Avoid leaking them. [1] https://learn.microsoft.com/en-us/windows/console/console-modes Issue: #26924 --- Source/cmStdIoStream.cxx | 19 +++++++++++++++---- Source/cmStdIoStream.h | 2 ++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Source/cmStdIoStream.cxx b/Source/cmStdIoStream.cxx index 9f448f2c84..4abe6050ec 100644 --- a/Source/cmStdIoStream.cxx +++ b/Source/cmStdIoStream.cxx @@ -115,17 +115,16 @@ Stream::Stream(std::ios& s, FILE* file, Direction direction) , FD_(cm_fileno(file)) { #ifdef _WIN32 - DWORD mode; auto h = reinterpret_cast(_get_osfhandle(this->FD_)); - if (GetConsoleMode(h, &mode)) { + if (GetConsoleMode(h, &this->ConsoleOrigMode_)) { this->Console_ = h; - DWORD vtMode = mode | + DWORD vtMode = this->ConsoleOrigMode_ | (direction == Direction::In ? ENABLE_VIRTUAL_TERMINAL_INPUT : ENABLE_VIRTUAL_TERMINAL_PROCESSING); if (SetConsoleMode(this->Console_, vtMode)) { this->Kind_ = TermKind::VT100; } else { - SetConsoleMode(this->Console_, mode); + SetConsoleMode(this->Console_, this->ConsoleOrigMode_); this->Kind_ = TermKind::Console; } } @@ -137,6 +136,18 @@ Stream::Stream(std::ios& s, FILE* file, Direction direction) #endif } +#ifdef _WIN32 +Stream::~Stream() +{ + if (this->Console_) { + this->IOS_.rdbuf()->pubsync(); + SetConsoleMode(this->Console_, this->ConsoleOrigMode_); + } +} +#else +Stream::~Stream() = default; +#endif + IStream::IStream(std::istream& is, FILE* file) : Stream(is, file, Direction::In) { diff --git a/Source/cmStdIoStream.h b/Source/cmStdIoStream.h index c3d28ce8eb..8ff84f93cf 100644 --- a/Source/cmStdIoStream.h +++ b/Source/cmStdIoStream.h @@ -53,6 +53,7 @@ protected: }; Stream(std::ios& s, FILE* file, Direction direction); + ~Stream(); // NOLINT(performance-trivially-destructible) private: std::ios& IOS_; @@ -61,6 +62,7 @@ private: #ifdef _WIN32 void* Console_ = nullptr; + unsigned long ConsoleOrigMode_ = 0; #endif };