From 57fd11a08da9a8b2f530bd9046c3c5bc0d175f41 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Thu, 12 May 2016 14:32:13 -0700 Subject: [PATCH] Use a JIT-specific stdout `FILE*`. Historically, the JIT has had issues with logging inside of processes that change the output mode of stdout (e.g. crossgen). This change replaces the previous solution (which relied on #ifdefs) by dup'ing the stdout file and wrapping it in a new `FILE*` set to a known output mode. Commit migrated from https://github.com/dotnet/coreclr/commit/8172ccaa93df60a46712f3453a4871ce0026f3ea --- src/coreclr/src/jit/codegencommon.cpp | 4 +-- src/coreclr/src/jit/compiler.cpp | 20 ++++++-------- src/coreclr/src/jit/compiler.h | 2 +- src/coreclr/src/jit/disasm.cpp | 8 +++--- src/coreclr/src/jit/ee_il_dll.cpp | 28 +++++++++++++++++++ src/coreclr/src/jit/error.cpp | 52 ++++++++++++++--------------------- src/coreclr/src/jit/flowgraph.cpp | 4 +-- src/coreclr/src/jit/gentree.cpp | 6 ++-- src/coreclr/src/jit/host.h | 30 ++++++++++---------- src/coreclr/src/jit/inline.cpp | 4 +-- 10 files changed, 86 insertions(+), 72 deletions(-) diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 0879ad6..027b19a 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -3094,7 +3094,7 @@ void CodeGen::genGenerateCode(void * * codePtr, genCreateAndStoreGCInfo(codeSize, prologSize, epilogSize DEBUGARG(codePtr)); #ifdef DEBUG - FILE* dmpf = stdout; + FILE* dmpf = jitstdout; compiler->opts.dmpHex = false; if (!strcmp(compiler->info.compMethodName, " // For _dup, _setmode +#include // For _O_TEXT +#endif /*****************************************************************************/ +FILE* jitstdout = nullptr; + ICorJitHost* g_jitHost = nullptr; static CILJit* ILJitter = 0; // The one and only JITTER I return #ifndef FEATURE_MERGE_JIT_AND_ENGINE @@ -61,6 +71,18 @@ void __stdcall jitStartup(ICorJitHost* jitHost) JitConfig.initialize(jitHost); } +#if defined(PLATFORM_UNIX) + jitstdout = stdout; +#else + if (jitstdout == nullptr) + { + int jitstdoutFd = _dup(_fileno(stdout)); + _setmode(jitstdoutFd, _O_TEXT); + jitstdout = _fdopen(jitstdoutFd, "w"); + assert(jitstdout != nullptr); + } +#endif + #ifdef FEATURE_TRACELOGGING JitTelemetry::NotifyDllProcessAttach(); #endif @@ -70,6 +92,12 @@ void __stdcall jitStartup(ICorJitHost* jitHost) void jitShutdown() { Compiler::compShutdown(); + + if (jitstdout != stdout) + { + fclose(jitstdout); + } + #ifdef FEATURE_TRACELOGGING JitTelemetry::NotifyDllProcessDetach(); #endif diff --git a/src/coreclr/src/jit/error.cpp b/src/coreclr/src/jit/error.cpp index 065d3f6..3d50f67 100644 --- a/src/coreclr/src/jit/error.cpp +++ b/src/coreclr/src/jit/error.cpp @@ -328,11 +328,15 @@ BOOL vlogf(unsigned level, const char* fmt, va_list args) return JitTls::GetLogEnv()->compHnd->logMsg(level, fmt, args); } -int logf_stdout(const char* fmt, va_list args) +int vflogf(FILE* file, const char* fmt, va_list args) { - // - // Fast logging to stdout - // + // 0-length string means flush + if (fmt[0] == '\0') + { + fflush(file); + return 0; + } + const int BUFF_SIZE = 8192; char buffer[BUFF_SIZE]; int written = _vsnprintf_s(&buffer[0], BUFF_SIZE, _TRUNCATE, fmt, args); @@ -341,32 +345,18 @@ int logf_stdout(const char* fmt, va_list args) { OutputDebugStringA(buffer); } + + // We use fputs here so that this executes as fast a possible + fputs(&buffer[0], file); + return written; +} - if (fmt[0] == 0) // null string means flush - { - fflush(stdout); - } - else - { -#if defined(CROSSGEN_COMPILE) && !defined(PLATFORM_UNIX) - // Crossgen has forced stdout into UNICODE only mode: - // _setmode(_fileno(stdout), _O_U8TEXT); - // - wchar_t wbuffer[BUFF_SIZE]; - - // Convert char* 'buffer' to a wchar_t* string. - size_t convertedChars = 0; - mbstowcs_s(&convertedChars, &wbuffer[0], BUFF_SIZE, buffer, _TRUNCATE); - - fputws(&wbuffer[0], stdout); -#else // CROSSGEN_COMPILE - // - // We use fputs here so that this executes as fast a possible - // - fputs(&buffer[0], stdout); -#endif // CROSSGEN_COMPILE - } - +int flogf(FILE* file, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + int written = vflogf(file, fmt, args); + va_end(args); return written; } @@ -395,7 +385,7 @@ int logf(const char* fmt, ...) { // if the EE refuses to log it, we try to send it to stdout va_start(args, fmt); - written = logf_stdout(fmt, args); + written = vflogf(jitstdout, fmt, args); va_end(args); } #if 0 // Enable this only when you need it @@ -454,7 +444,7 @@ void gcDump_logf(const char* fmt, ...) { // if the EE refuses to log it, we try to send it to stdout va_start(args, fmt); - logf_stdout(fmt, args); + vflogf(jitstdout, fmt, args); va_end(args); } #if 0 // Enable this only when you need it diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp index 24312f2..a66fa40 100644 --- a/src/coreclr/src/jit/flowgraph.cpp +++ b/src/coreclr/src/jit/flowgraph.cpp @@ -19188,7 +19188,7 @@ ONE_FILE_PER_METHOD:; } else if (wcscmp(filename, W("stdout")) == 0) { - fgxFile = stdout; + fgxFile = jitstdout; *wbDontClose = true; } else if (wcscmp(filename, W("stderr")) == 0) @@ -19527,7 +19527,7 @@ bool Compiler::fgDumpFlowGraph(Phases phase) if (dontClose) { - // fgxFile is stdout or stderr + // fgxFile is jitstdout or stderr fprintf(fgxFile, "\n"); } else diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp index 53101d8..e907d50 100644 --- a/src/coreclr/src/jit/gentree.cpp +++ b/src/coreclr/src/jit/gentree.cpp @@ -7512,7 +7512,7 @@ void Compiler::gtDispVN(GenTree* tree) } //------------------------------------------------------------------------ -// gtDispNode: Print a tree to stdout. +// gtDispNode: Print a tree to jitstdout. // // Arguments: // tree - the tree to be printed @@ -8257,7 +8257,7 @@ void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn) } //------------------------------------------------------------------------ -// gtDispLeaf: Print a single leaf node to stdout. +// gtDispLeaf: Print a single leaf node to jitstdout. // // Arguments: // tree - the tree to be printed @@ -8496,7 +8496,7 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) } //------------------------------------------------------------------------ -// gtDispLeaf: Print a child node to stdout. +// gtDispLeaf: Print a child node to jitstdout. // // Arguments: // tree - the tree to be printed diff --git a/src/coreclr/src/jit/host.h b/src/coreclr/src/jit/host.h index f6d701f..bf1f60e 100644 --- a/src/coreclr/src/jit/host.h +++ b/src/coreclr/src/jit/host.h @@ -9,6 +9,10 @@ #define printf logf #endif +#ifndef fprintf +#define fprintf flogf +#endif + class Compiler; class LogEnv { @@ -21,27 +25,14 @@ public: }; BOOL vlogf(unsigned level, const char* fmt, va_list args); +int vflogf(FILE* file, const char* fmt, va_list args); -int logf_stdout(const char* fmt, va_list args); -int logf(const char*, ...); +int logf(const char* fmt, ...); +int flogf(FILE* file, const char* fmt, ...); void gcDump_logf(const char* fmt, ...); void logf(unsigned level, const char* fmt, ...); -#if defined(CROSSGEN_COMPILE) && !defined(PLATFORM_UNIX) && !defined(fprintf) -// On Windows, CrossGen configures its stdout to allow Unicode output only. -// The following wrapper allows fprintf to work with stdout. -inline int fprintfCrossgen(FILE *stream, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - int ret = stream == stdout ? logf_stdout(fmt, args) : vfprintf(stream, fmt, args); - va_end(args); - return ret; -} -#define fprintf fprintfCrossgen -#endif - extern "C" void __cdecl assertAbort(const char *why, const char *file, unsigned line); @@ -61,6 +52,13 @@ void __cdecl assertAbort(const char *why, const char *file, unsigned line const size_t OS_page_size = (4*1024); +extern FILE* jitstdout; + +#if !defined(ALLOW_STDOUT) +#undef stdout +#define stdout use_jitstdout +#endif + /*****************************************************************************/ #endif /*****************************************************************************/ diff --git a/src/coreclr/src/jit/inline.cpp b/src/coreclr/src/jit/inline.cpp index 1f728dd..f39c553 100644 --- a/src/coreclr/src/jit/inline.cpp +++ b/src/coreclr/src/jit/inline.cpp @@ -345,7 +345,7 @@ InlineContext::InlineContext(InlineStrategy* strategy) #if defined(DEBUG) || defined(INLINE_DATA) //------------------------------------------------------------------------ -// Dump: Dump an InlineContext entry and all descendants to stdout +// Dump: Dump an InlineContext entry and all descendants to jitstdout // // Arguments: // indent - indentation level for this node @@ -451,7 +451,7 @@ void InlineContext::DumpData(unsigned indent) { const char* inlineReason = InlGetObservationString(m_Observation); printf("%*s%u,\"%s\",\"%s\"", indent, "", m_Ordinal, inlineReason, calleeName); - m_Policy->DumpData(stdout); + m_Policy->DumpData(jitstdout); printf("\n"); } -- 2.7.4