diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2020-07-01 16:29:59 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2020-07-01 16:29:59 -0400 | 
| commit | 01128f9f945f20bc3c472ed953cb0c0fae6ce407 (patch) | |
| tree | bfbf58e882aa1a3df4ff4f15e34ca7e12c67e456 /indra/newview | |
| parent | d8649dbb8a5a20753248923a25c13f729cadd99a (diff) | |
DRTVWR-476, SL-13528: Use freopen_s() instead of assigning stderr.
The llappviewerwin32.cpp create_console() function called by
LLAppViewerWin32::initConsole() used to assign *stderr = *(new FILE* value),
and so forth for stdout and stdin. That dubious tactic no longer works with
the new Windows CRT introduced with VS 2015. freopen_s() works much better.
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/llappviewerwin32.cpp | 100 | 
1 files changed, 51 insertions, 49 deletions
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index f0aa355342..156a1c5893 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -507,63 +507,65 @@ const S32 MAX_CONSOLE_LINES = 500;  namespace { -FILE* set_stream(const char* which, DWORD handle_id, const char* mode); +void set_stream(const char* desc, FILE* fp, DWORD handle_id, const char* name, const char* mode="w");  bool create_console()  { -	// allocate a console for this app -	const bool isConsoleAllocated = AllocConsole(); - -	// set the screen buffer to be big enough to let us scroll text -	CONSOLE_SCREEN_BUFFER_INFO coninfo; -	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); -	coninfo.dwSize.Y = MAX_CONSOLE_LINES; -	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); - -	// redirect unbuffered STDOUT to the console -	FILE* fp = set_stream("stdout", STD_OUTPUT_HANDLE, "w"); -	if (fp) -	{ -		*stdout = *fp; -	} - -	// redirect unbuffered STDIN to the console -	fp = set_stream("stdin", STD_INPUT_HANDLE, "r"); -	if (fp) -	{ -		*stdin = *fp; -	} +    // allocate a console for this app +    const bool isConsoleAllocated = AllocConsole(); -	// redirect unbuffered STDERR to the console -	fp = set_stream("stderr", STD_ERROR_HANDLE, "w"); -	if (fp) -	{ -		*stderr = *fp; -	} +    if (isConsoleAllocated) +    { +        // set the screen buffer to be big enough to let us scroll text +        CONSOLE_SCREEN_BUFFER_INFO coninfo; +        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); +        coninfo.dwSize.Y = MAX_CONSOLE_LINES; +        SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); + +        // redirect unbuffered STDOUT to the console +        set_stream("stdout", stdout, STD_OUTPUT_HANDLE, "CONOUT$"); +        // redirect unbuffered STDERR to the console +        set_stream("stderr", stderr, STD_ERROR_HANDLE, "CONOUT$"); +        // redirect unbuffered STDIN to the console +        // Don't bother: our console is solely for log output. We never read stdin. +//      set_stream("stdin", stdin, STD_INPUT_HANDLE, "CONIN$", "r"); +    } -	return isConsoleAllocated; +    return isConsoleAllocated;  } -FILE* set_stream(const char* desc, DWORD handle_id, const char* mode) +void set_stream(const char* desc, FILE* fp, DWORD handle_id, const char* name, const char* mode)  { -	auto l_std_handle = GetStdHandle(handle_id); -	int h_con_handle = _open_osfhandle(reinterpret_cast<intptr_t>(l_std_handle), _O_TEXT); -	if (h_con_handle == -1) -	{ -		LL_WARNS() << "create_console() failed to open " << desc << " handle" << LL_ENDL; -		return nullptr; -	} -	else -	{ -		FILE* fp = _fdopen( h_con_handle, mode ); -		setvbuf( fp, NULL, _IONBF, 0 ); -		// Enable color processing on Windows 10 console windows. -		DWORD dwMode = 0; -		GetConsoleMode(l_std_handle, &dwMode); -		dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; -		SetConsoleMode(l_std_handle, dwMode); -		return fp; -	} +    // SL-13528: This code used to be based on +    // http://dslweb.nwnexus.com/~ast/dload/guicon.htm +    // (referenced in https://stackoverflow.com/a/191880). +    // But one of the comments on that StackOverflow answer points out that +    // assigning to *stdout or *stderr "probably doesn't even work with the +    // Universal CRT that was introduced in 2015," suggesting freopen_s() +    // instead. Code below is based on https://stackoverflow.com/a/55875595. +    auto std_handle = GetStdHandle(handle_id); +    if (std_handle == INVALID_HANDLE_VALUE) +    { +        LL_WARNS() << "create_console() failed to get " << desc << " handle" << LL_ENDL; +    } +    else +    { +        if (mode == std::string("w")) +        { +            // Enable color processing on Windows 10 console windows. +            DWORD dwMode = 0; +            GetConsoleMode(std_handle, &dwMode); +            dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; +            SetConsoleMode(std_handle, dwMode); +        } +        // Redirect the passed fp to the console. +        FILE* ignore; +        if (freopen_s(&ignore, name, mode, fp) == 0) +        { +            // use unbuffered I/O +            setvbuf( fp, NULL, _IONBF, 0 ); +        } +    }  }  } // anonymous namespace  | 
