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
This commit is contained in:
Brad King
2025-05-23 09:03:03 -04:00
parent 12d8baadab
commit fb3e7825f3
2 changed files with 17 additions and 4 deletions
+15 -4
View File
@@ -115,17 +115,16 @@ Stream::Stream(std::ios& s, FILE* file, Direction direction)
, FD_(cm_fileno(file)) , FD_(cm_fileno(file))
{ {
#ifdef _WIN32 #ifdef _WIN32
DWORD mode;
auto h = reinterpret_cast<HANDLE>(_get_osfhandle(this->FD_)); auto h = reinterpret_cast<HANDLE>(_get_osfhandle(this->FD_));
if (GetConsoleMode(h, &mode)) { if (GetConsoleMode(h, &this->ConsoleOrigMode_)) {
this->Console_ = h; this->Console_ = h;
DWORD vtMode = mode | DWORD vtMode = this->ConsoleOrigMode_ |
(direction == Direction::In ? ENABLE_VIRTUAL_TERMINAL_INPUT (direction == Direction::In ? ENABLE_VIRTUAL_TERMINAL_INPUT
: ENABLE_VIRTUAL_TERMINAL_PROCESSING); : ENABLE_VIRTUAL_TERMINAL_PROCESSING);
if (SetConsoleMode(this->Console_, vtMode)) { if (SetConsoleMode(this->Console_, vtMode)) {
this->Kind_ = TermKind::VT100; this->Kind_ = TermKind::VT100;
} else { } else {
SetConsoleMode(this->Console_, mode); SetConsoleMode(this->Console_, this->ConsoleOrigMode_);
this->Kind_ = TermKind::Console; this->Kind_ = TermKind::Console;
} }
} }
@@ -137,6 +136,18 @@ Stream::Stream(std::ios& s, FILE* file, Direction direction)
#endif #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) IStream::IStream(std::istream& is, FILE* file)
: Stream(is, file, Direction::In) : Stream(is, file, Direction::In)
{ {
+2
View File
@@ -53,6 +53,7 @@ protected:
}; };
Stream(std::ios& s, FILE* file, Direction direction); Stream(std::ios& s, FILE* file, Direction direction);
~Stream(); // NOLINT(performance-trivially-destructible)
private: private:
std::ios& IOS_; std::ios& IOS_;
@@ -61,6 +62,7 @@ private:
#ifdef _WIN32 #ifdef _WIN32
void* Console_ = nullptr; void* Console_ = nullptr;
unsigned long ConsoleOrigMode_ = 0;
#endif #endif
}; };