From 9019d4e654d717fb4fd07ed46e82e3beb9a50166 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Tue, 4 Mar 2025 15:42:07 +0100 Subject: [PATCH 01/14] Add Android logging support to a couple of runtime files. --- src/coreclr/inc/utilcode.h | 1 + src/coreclr/jit/ee_il_dll.cpp | 21 +- src/coreclr/jit/error.cpp | 13 +- src/coreclr/pal/src/thread/process.cpp | 11 + src/coreclr/utilcode/log.cpp | 5 +- src/coreclr/vm/eepolicy.cpp | 41 ++- .../vm/eventing/eventpipe/ds-rt-coreclr.h | 9 +- src/coreclr/vm/excep.cpp | 37 +- src/coreclr/vm/util.cpp | 89 ----- src/coreclr/vm/util.hpp | 3 - src/native/minipal/CMakeLists.txt | 5 + src/native/minipal/log.c | 329 ++++++++++++++++++ src/native/minipal/log.h | 85 +++++ 13 files changed, 504 insertions(+), 145 deletions(-) create mode 100644 src/native/minipal/log.c create mode 100644 src/native/minipal/log.h diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index 9b8e1ee3dfd704..0221afafe08c9b 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -37,6 +37,7 @@ using std::nothrow; #include #include +#include #include #include "clrnt.h" diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 3d251f4e7bd192..f954ca6e90592f 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -29,9 +29,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #define DLLEXPORT #endif // !DLLEXPORT -#if defined(HOST_ANDROID) -#include -#endif +#include "minipal/log.h" /*****************************************************************************/ @@ -150,16 +148,19 @@ FILE* jitstdout() // Like printf/logf, but only outputs to jitstdout -- skips call back into EE. int jitprintf(const char* fmt, ...) { + int status; va_list vl; va_start(vl, fmt); -#if defined(HOST_ANDROID) - int status = jitstdout() == procstdout() - ? __android_log_vprint(ANDROID_LOG_VERBOSE, MAIN_CLR_MODULE_NAME_A, fmt, vl) - : vfprintf(jitstdout(), fmt, vl); -#else - int status = vfprintf(jitstdout(), fmt, vl); -#endif + if (jitstdout() == procstdout()) + { + status = minipal_log_vprint_verbose(fmt, vl); + } + else + { + status = vfprintf(jitstdout(), fmt, vl); + } va_end(vl); + return status; } diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index 5ae6cea056efeb..fee244db7da366 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -15,6 +15,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #pragma hdrstop #endif #include "compiler.h" +#include "minipal/log.h" #if MEASURE_FATAL unsigned fatal_badCode; @@ -318,7 +319,10 @@ int vflogf(FILE* file, const char* fmt, va_list args) // 0-length string means flush if (fmt[0] == '\0') { - fflush(file); + if (file == procstdout()) + minipal_log_flush_verbose(); + else + fflush(file); return 0; } @@ -331,8 +335,11 @@ int vflogf(FILE* file, const char* fmt, va_list args) OutputDebugStringA(buffer); } - // We use fputs here so that this executes as fast a possible - fputs(&buffer[0], file); + if (file == procstdout()) + minipal_log_write_verbose(buffer); + else + fputs(&buffer[0], file); + return written; } diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 1688d3b16779bf..e9596e2ea9aba7 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2452,6 +2452,16 @@ PAL_GenerateCoreDump( (no return value) --*/ +#ifdef HOST_ANDROID +#include +VOID +PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize) +{ + // TODO: Dump all managed threads callstacks into logcat and/or file? + // TODO: Dump stress log into logcat and/or file when enabled? + minipal_log_write_fatal("Aborting process.\n"); +} +#else VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize) { @@ -2520,6 +2530,7 @@ PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize) free(signalAddressArg); } } +#endif /*++ Function: diff --git a/src/coreclr/utilcode/log.cpp b/src/coreclr/utilcode/log.cpp index 56ddf6aef9c20e..e1c59408beb192 100644 --- a/src/coreclr/utilcode/log.cpp +++ b/src/coreclr/utilcode/log.cpp @@ -372,10 +372,10 @@ VOID LogSpewAlwaysValist(const char *fmt, va_list args) if (LogFlags & LOG_ENABLE_CONSOLE_LOGGING) { - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pBuffer, buflen, &written, 0); + minipal_log_write_stdout(pBuffer); //@TODO ...Unnecessary to flush console? if (LogFlags & LOG_ENABLE_FLUSH_FILE) - FlushFileBuffers( GetStdHandle(STD_OUTPUT_HANDLE) ); + minipal_log_sync_stdout(); } if (LogFlags & LOG_ENABLE_DEBUGGER_LOGGING) @@ -415,6 +415,5 @@ VOID LogSpewAlways (const char *fmt, ... ) LogSpewValist (LF_ALWAYS, LL_ALWAYS, fmt, args); va_end(args); } - #endif // LOGGING diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index fe435ce8d569dc..96076690a5e8d0 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -48,7 +48,7 @@ void SafeExitProcess(UINT exitCode, ShutdownCompleteAction sca = SCA_ExitProcess { _ASSERTE(!"Bad Exit value"); FAULT_NOT_FATAL(); // if we OOM we can simply give up - fprintf(stderr, "Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); + minipal_log_print_stderr("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); DebugBreak(); } } @@ -233,8 +233,10 @@ class CallStackLogger MethodDesc* pMD = m_frames[index]; TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature); - PrintToStdErrW(str.GetUnicode()); - PrintToStdErrA("\n"); + str.Append(W("\n")); + + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(strUTF8, str.GetUnicode(), CP_UTF8); + minipal_log_write_stderr(strUTF8); } public: @@ -264,13 +266,15 @@ class CallStackLogger SmallStackSString repeatStr; repeatStr.AppendPrintf("Repeated %d times:\n", m_largestCommonStartRepeat); - PrintToStdErrW(repeatStr.GetUnicode()); - PrintToStdErrA("--------------------------------\n"); + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(repeatStrUTF8, repeatStr.GetUnicode(), CP_UTF8); + minipal_log_write_stderr(repeatStrUTF8); + + minipal_log_write_stderr("--------------------------------\n"); for (int i = 0; i < m_largestCommonStartLength; i++) { PrintFrame(i, pWordAt); } - PrintToStdErrA("--------------------------------\n"); + minipal_log_write_stderr("--------------------------------\n"); } for (int i = m_largestCommonStartLength * m_largestCommonStartRepeat; i < m_frames.Count(); i++) @@ -356,7 +360,7 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS { if (previousThreadID == currentThreadID) { - PrintToStdErrA("Fatal error while logging another fatal error.\n"); + minipal_log_write_stderr("Fatal error while logging another fatal error.\n"); } else { @@ -371,34 +375,38 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS EX_TRY { + SString message; if (exitCode == (UINT)COR_E_FAILFAST) { - PrintToStdErrA("Process terminated. "); + message.Append(W("Process terminated. ")); } else { - PrintToStdErrA("Fatal error. "); + message.Append(W("Fatal error. ")); } if (errorSource != NULL) { - PrintToStdErrW(errorSource); - PrintToStdErrA("\n"); + message.Append(errorSource); + message.Append(W("\n")); } if (pszMessage != NULL) { - PrintToStdErrW(pszMessage); + message.Append(pszMessage); } else { // If no message was passed in, generate it from the exitCode SString exitCodeMessage; GetHRMsg(exitCode, exitCodeMessage); - PrintToStdErrW((LPCWSTR)exitCodeMessage); + message.Append(exitCodeMessage); } - PrintToStdErrA("\n"); + message.Append(W("\n")); + + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(messageUTF8, message.GetUnicode(), CP_UTF8); + minipal_log_write_stderr(messageUTF8); Thread* pThread = GetThreadNULLOk(); if (pThread && errorSource == NULL) @@ -406,7 +414,8 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS LogCallstackForLogWorker(pThread, pExceptionInfo); if (argExceptionString != NULL) { - PrintToStdErrW(argExceptionString); + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(argExceptionStringUTF8, argExceptionString, CP_UTF8); + minipal_log_write_stderr(argExceptionStringUTF8); } } } @@ -598,7 +607,7 @@ void DisplayStackOverflowException() { LIMITED_METHOD_CONTRACT; - PrintToStdErrA("Stack overflow.\n"); + minipal_log_write_stderr("Stack overflow.\n"); } DWORD LogStackOverflowStackTraceThread(void* arg) diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index fb6c0c3feeda09..e86b6c68b54252 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -11,6 +11,7 @@ #include "ep-rt-coreclr.h" #include #include +#include #include #include #include @@ -404,10 +405,10 @@ ds_rt_server_log_pause_message (void) uint32_t port_suspended = ds_rt_config_value_get_default_port_suspend(); - printf("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); - printf("DOTNET_%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports); - printf("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended); - fflush(stdout); + minipal_log_print_stdout("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); + minipal_log_print_stdout("DOTNET_%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports); + minipal_log_print_stdout("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended); + minipal_log_flush_stdout(); } #endif /* ENABLE_PERFTRACING */ diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 7bd720baf28676..e2c4564293768e 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4550,7 +4550,7 @@ lDone: ; char buffer[200]; sprintf_s(buffer, 200, "\nInternal error: Uncaught exception was thrown from IP = %p in UnhandledExceptionFilter_Worker on thread 0x%08x\n", param.ExceptionEIP, ((GetThreadNULLOk() == NULL) ? 0 : GetThread()->GetThreadId())); - PrintToStdErrA(buffer); + minipal_log_write_stderr(buffer); _ASSERTE(!"Unexpected exception in UnhandledExceptionFilter_Worker"); #endif EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE) @@ -4756,8 +4756,6 @@ LONG __stdcall COMUnhandledExceptionFilter( // EXCEPTION_CONTINUE_SEARCH or #pragma code_seg(pop, uef) #endif // !TARGET_UNIX -void PrintStackTraceToStdout(); - static SString GetExceptionMessageWrapper(Thread* pThread, OBJECTREF throwable) { STATIC_CONTRACT_THROWS; @@ -4788,17 +4786,18 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, wcsncpy_s(buf, buf_size, SZ_UNHANDLED_EXCEPTION, SZ_UNHANDLED_EXCEPTION_CHARLEN); } - PrintToStdErrW(buf); - PrintToStdErrA(" "); - - SString message = GetExceptionMessageWrapper(pThread, throwable); + SString message(buf); + SString exceptionMessage = GetExceptionMessageWrapper(pThread, throwable); - if (!message.IsEmpty()) + message.Append(W(" ")); + if (!exceptionMessage.IsEmpty()) { - PrintToStdErrW(message); + message.Append(exceptionMessage); } + message.Append(W("\n")); - PrintToStdErrA("\n"); + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(messageUTF8, message.GetUnicode(), CP_UTF8); + minipal_log_write_stderr(messageUTF8); #if defined(FEATURE_EVENT_TRACE) && !defined(TARGET_UNIX) // Send the log to Windows Event Log @@ -4980,11 +4979,11 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, if (IsOutOfMemory) { - PrintToStdErrA("Out of memory.\n"); + minipal_log_write_stderr("Out of memory.\n"); } else { - PrintToStdErrA("Stack overflow.\n"); + minipal_log_write_stderr("Stack overflow.\n"); } } else if (SentEvent || IsAsyncThreadException(&throwable)) @@ -5005,17 +5004,21 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, EX_CATCH { LOG((LF_EH, LL_INFO10, "Exception occurred while processing uncaught exception\n")); - UtilLoadStringRC(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf, buf_size); - PrintToStdErrA("\n "); - PrintToStdErrW(buf); - PrintToStdErrA("\n"); + + _ASSERTE(buf_size > 6); + wcscpy_s(buf, buf_size, W("\n ")); + UtilLoadStringRC(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf + 4, buf_size - 6); + wcscat_s(buf, buf_size, W("\n")); + + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(bufUTF8, buf, CP_UTF8); + minipal_log_write_stderr(bufUTF8); } EX_END_CATCH(SwallowAllExceptions); } EX_CATCH { // If we got here, we can't even print the localized error message. Print non-localized. LOG((LF_EH, LL_INFO10, "Exception occurred while logging processing uncaught exception\n")); - PrintToStdErrA("\n Error: Can't print exception string because Exception.ToString() failed.\n"); + minipal_log_write_stderr("\n Error: Can't print exception string because Exception.ToString() failed.\n"); } EX_END_CATCH(SwallowAllExceptions); } diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 4fc2242095a37b..8185f8780e791e 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -15,10 +15,6 @@ #ifndef DACCESS_COMPILE -#if defined(TARGET_ANDROID) -#include -#endif // defined(TARGET_ANDROID) - thread_local size_t t_ThreadType; void ClrFlsSetThreadType(TlsThreadTypeFlag flag) @@ -120,91 +116,6 @@ LPVOID CQuickHeap::Alloc(UINT sz) } } -//---------------------------------------------------------------------------- -// Output functions that avoid the crt's. -//---------------------------------------------------------------------------- - -static -void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - FORBID_FAULT; - } - CONTRACTL_END - - if (Handle == INVALID_HANDLE_VALUE || Handle == NULL) - return; - - BOOL success; - DWORD dwBytesWritten; - const size_t maxWriteFileSize = 32767; // This is somewhat arbitrary limit, but 2**16-1 doesn't work - - while (BytesToWrite > 0) { - DWORD dwChunkToWrite = (DWORD) min(BytesToWrite, maxWriteFileSize); - - // Try to write to handle. If this is not a CUI app, then this is probably - // not going to work unless the dev took special pains to set their own console - // handle during CreateProcess. So try it, but don't yell if it doesn't work in - // that case. Also, if we redirect stdout to a pipe then the pipe breaks (ie, we - // write to something like the UNIX head command), don't complain. - success = WriteFile(Handle, pszString, dwChunkToWrite, &dwBytesWritten, NULL); - if (!success) - { -#if defined(_DEBUG) - // This can happen if stdout is a closed pipe. This might not help - // much, but we'll have half a chance of seeing this. - OutputDebugStringA("CLR: Writing out an unhandled exception to stdout failed!\n"); - OutputDebugStringA(pszString); -#endif //_DEBUG - - break; - } - else { - _ASSERTE(dwBytesWritten == dwChunkToWrite); - } - pszString = pszString + dwChunkToWrite; - BytesToWrite -= dwChunkToWrite; - } - -} - -void PrintToStdErrA(const char *pszString) { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - FORBID_FAULT; - } - CONTRACTL_END - -#if defined(TARGET_ANDROID) - __android_log_write(ANDROID_LOG_FATAL, MAIN_CLR_MODULE_NAME_A, pszString); -#else - HANDLE Handle = GetStdHandle(STD_ERROR_HANDLE); - size_t len = strlen(pszString); - NPrintToHandleA(Handle, pszString, len); -#endif // defined(TARGET_ANDROID) -} - -void PrintToStdErrW(const WCHAR *pwzString) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END - - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(pStr, pwzString, GetConsoleOutputCP()); - - PrintToStdErrA(pStr); -} -//---------------------------------------------------------------------------- - //***************************************************************************** // Compare VarLoc's //***************************************************************************** diff --git a/src/coreclr/vm/util.hpp b/src/coreclr/vm/util.hpp index e4315c6181c272..3c67f9bf6565cf 100644 --- a/src/coreclr/vm/util.hpp +++ b/src/coreclr/vm/util.hpp @@ -189,9 +189,6 @@ class CQuickHeap QuickBlock *m_pFirstBigQuickBlock; }; -void PrintToStdErrA(const char *pszString); -void PrintToStdErrW(const WCHAR *pwzString); - #include "nativevaraccessors.h" // -------------------------------------------------------------------------------- diff --git a/src/native/minipal/CMakeLists.txt b/src/native/minipal/CMakeLists.txt index 8ebacd8cd6f404..18473da705d609 100644 --- a/src/native/minipal/CMakeLists.txt +++ b/src/native/minipal/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES unicodedata.c utf8.c xoshiro128pp.c + log.c ) # Provide an object library for scenarios where we ship static libraries @@ -36,6 +37,10 @@ endif() add_library(minipal STATIC) target_link_libraries(minipal PRIVATE minipal_objects) +if(CLR_CMAKE_TARGET_ANDROID) + target_link_libraries(minipal PRIVATE log) +endif(CLR_CMAKE_TARGET_ANDROID) + add_library(minipal_sanitizer_support OBJECT sansupport.c) # Exclude this target from the default build as we may not have sanitzer headers available diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c new file mode 100644 index 00000000000000..ea81a1fb391b43 --- /dev/null +++ b/src/native/minipal/log.c @@ -0,0 +1,329 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "log.h" +#include + +#ifndef MINIPAL_LOG_RUNTIME_TAG +#define MINIPAL_LOG_RUNTIME_TAG "DOTNET" +#endif + +#ifdef HOST_ANDROID +#include +#include + +// Android defines its LOGGER_ENTRY_MAX_PAYLOAD to 4068 bytes. +// Use 4000 bytes to include some slack for future changes to LOGGER_ENTRY_MAX_PAYLOAD. +#define MINIPAL_LOG_MAX_PAYLOAD 4000 + +// Android defines its internal log buffer used in __android_log_vprint to 1024 bytes. +// Use same internal stack buffer size avoiding dynamic memory allocation for majority of logging. +#define MINIPAL_LOG_BUF_SIZE 1024 + +static int android_log_flag(minipal_log_flags flags) +{ + switch(flags) + { + case minipal_log_flags_fatal: + return ANDROID_LOG_FATAL; + case minipal_log_flags_error: + return ANDROID_LOG_ERROR; + case minipal_log_flags_warning: + return ANDROID_LOG_WARN; + case minipal_log_flags_info: + return ANDROID_LOG_INFO; + case minipal_log_flags_debug: + return ANDROID_LOG_DEBUG; + case minipal_log_flags_verbose: + return ANDROID_LOG_VERBOSE; + default: + return ANDROID_LOG_UNKNOWN; + } +} + +static size_t log_write(minipal_log_flags flags, const char* msg, size_t msg_len) +{ + return __android_log_write(android_log_flag(flags), MINIPAL_LOG_RUNTIME_TAG, msg) == 1 ? msg_len : 0; +} + +int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + int bytes_written = minipal_log_vprint(flags, fmt, args); + va_end(args); + return bytes_written; +} + +int minipal_log_vprint(minipal_log_flags flags, const char* fmt, va_list args) +{ + char stack_buffer[MINIPAL_LOG_BUF_SIZE]; + int bytes_written = 0; + va_list args_copy; + + va_copy(args_copy, args); + + int len = vsnprintf(stack_buffer, sizeof(stack_buffer), fmt, args_copy); + if (len < sizeof(stack_buffer)) + { + bytes_written = minipal_log_write(flags, stack_buffer); + } + else + { + char* dyn_buffer = (char*)malloc(len + 1); + if (dyn_buffer != NULL) + { + vsnprintf(dyn_buffer, len + 1, fmt, args); + bytes_written = minipal_log_write(flags, dyn_buffer); + free(dyn_buffer); + } + } + + va_end(args_copy); + return bytes_written; +} + +void minipal_log_flush(minipal_log_flags flags) +{ + ; +} + +static size_t log_write_line(minipal_log_flags flags, const char* msg, size_t msg_len) +{ + char buffer[MINIPAL_LOG_MAX_PAYLOAD]; + if (msg_len < MINIPAL_LOG_MAX_PAYLOAD) + { + strncpy(buffer, msg, msg_len); + buffer[msg_len] = '\0'; + return log_write(flags, buffer, msg_len); + } + + const char* msg_end = msg + msg_len; + size_t bytes_written = 0; + while (msg < msg_end) + { + ptrdiff_t chunk_size = MINIPAL_LOG_MAX_PAYLOAD - 1; + if (msg_end - msg < chunk_size) + { + chunk_size = msg_end - msg; + } + + strncpy(buffer, msg, chunk_size); + buffer[chunk_size] = '\0'; + bytes_written += log_write(flags, buffer, chunk_size); + msg += chunk_size; + } + + return bytes_written; +} + +int minipal_log_write(minipal_log_flags flags, const char* msg) +{ + if (msg == NULL || msg[0] == '\0') + return 0; + + size_t msg_len = strlen(msg); + const char* msg_end = msg + msg_len; + + if (msg_len < MINIPAL_LOG_MAX_PAYLOAD) + return (int)log_write(flags, msg, msg_len); + + const char* next_msg = NULL; + size_t bytes_written = 0; + for (next_msg = msg; next_msg < msg_end;) + { + const char* next_line_break = strchr(next_msg, '\n'); + if (next_line_break == NULL && (msg_end - next_msg < MINIPAL_LOG_MAX_PAYLOAD)) + { + bytes_written += log_write(flags, next_msg, msg_end - next_msg); + break; + } + else if (next_line_break == NULL) + { + bytes_written += log_write_line(flags, next_msg, msg_end - next_msg); + break; + } + else + { + bytes_written += log_write_line(flags, next_msg, next_line_break - next_msg); + next_msg = next_line_break + 1; + } + } + + return (int)bytes_written; +} + +void minipal_log_sync(minipal_log_flags flags) +{ + ; +} +#else +#include + +#define MINIPAL_LOG_MAX_PAYLOAD 32767 + +static FILE * get_std_file(minipal_log_flags flags) +{ + switch(flags) + { + case minipal_log_flags_fatal: + case minipal_log_flags_error: + return stderr; + case minipal_log_flags_warning: + case minipal_log_flags_info: + case minipal_log_flags_debug: + case minipal_log_flags_verbose: + default: + return stdout; + } +} + +int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + int status = vfprintf(get_std_file(flags), fmt, args); + va_end(args); + return status; +} + +int minipal_log_vprint(minipal_log_flags flags, const char* fmt, va_list args) +{ + return vfprintf(get_std_file(flags), fmt, args); +} + +void minipal_log_flush(minipal_log_flags flags) +{ + FILE* file = get_std_file(flags); + if (file != NULL) + fflush(file); +} + +#if defined(HOST_WINDOWS) +#include + +static HANDLE get_std_handle(minipal_log_flags flags) +{ + switch(flags) + { + case minipal_log_flags_fatal: + case minipal_log_flags_error: + return GetStdHandle(STD_ERROR_HANDLE); + case minipal_log_flags_warning: + case minipal_log_flags_info: + case minipal_log_flags_debug: + case minipal_log_flags_verbose: + default: + return GetStdHandle(STD_OUTPUT_HANDLE); + } +} + +static size_t write_file(HANDLE handle, const char* msg, size_t bytes_to_write) +{ + if (handle == INVALID_HANDLE_VALUE) + return 0; + + if (msg == NULL || msg[0] == '\0') + return 0; + + DWORD bytes_written = 0; + if (!WriteFile(handle, msg, (DWORD)bytes_to_write, &bytes_written, NULL)) + bytes_written = 0; + + return bytes_written; +} + +static void sync_file(HANDLE handle) +{ + if (handle == INVALID_HANDLE_VALUE) + return; + + FlushFileBuffers(handle); +} +#endif + +#if !defined(HOST_WINDOWS) +#include +#include +#include + +#define HANDLE int + +static HANDLE get_std_handle(minipal_log_flags flags) +{ + return fileno(get_std_file(flags)); +} + +static int write_file(HANDLE handle, const char* msg, size_t bytes_to_write) +{ + if (handle == -1) + return 0; + + if (msg == NULL || msg[0] == '\0') + return 0; + + return write(handle, msg, bytes_to_write); +} + +static void sync_file(HANDLE handle) +{ + if (handle == -1) + return; + + bool retry = false; +#if HAVE_FSYNC || defined(__APPLE__) + do + { +#if defined(__APPLE__) + if (fcntl(handle, F_FULLFSYNC) != -1) + break; +#else + if (fsync(handle) == 0) + break; +#endif + switch (errno) + { + case EINTR: + retry = true; + break; + default: + retry = false; + break; + } + } while (retry); +#else + sync(); +#endif +} +#endif + +int minipal_log_write(minipal_log_flags flags, const char* msg) +{ + if (msg == NULL || msg[0] == '\0') + return 0; + + size_t bytes_to_write = strlen(msg); + size_t bytes_written = 0; + + HANDLE handle = get_std_handle(flags); + while (bytes_to_write > 0) + { + size_t chunk_to_write = bytes_to_write < MINIPAL_LOG_MAX_PAYLOAD ? bytes_to_write : MINIPAL_LOG_MAX_PAYLOAD; + size_t chunk_written = write_file(handle, msg, chunk_to_write); + + if (chunk_written == 0) + break; + + msg = msg + chunk_written; + bytes_to_write -= chunk_written; + bytes_written += chunk_written; + } + + return (int)bytes_written; +} + +void minipal_log_sync(minipal_log_flags flags) +{ + sync_file(get_std_handle(flags)); +} +#endif diff --git a/src/native/minipal/log.h b/src/native/minipal/log.h new file mode 100644 index 00000000000000..33f0cb60c4a8cb --- /dev/null +++ b/src/native/minipal/log.h @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef HAVE_MINIPAL_LOG_H +#define HAVE_MINIPAL_LOG_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef enum +{ + minipal_log_flags_fatal = 1 << 1, + minipal_log_flags_error = 1 << 2, + minipal_log_flags_warning = 1 << 3, + minipal_log_flags_info = 1 << 4, + minipal_log_flags_debug = 1 << 5, + minipal_log_flags_verbose = 1 << 6 +} minipal_log_flags; + +#define minipal_log_flags_stderr minipal_log_flags_error +#define minipal_log_flags_stdout minipal_log_flags_info + +#define minipal_log_print_fatal(...) minipal_log_print(minipal_log_flags_fatal, __VA_ARGS__) +#define minipal_log_print_error(...) minipal_log_print(minipal_log_flags_error, __VA_ARGS__) +#define minipal_log_print_warning(...) minipal_log_print(minipal_log_flags_warning, __VA_ARGS__) +#define minipal_log_print_info(...) minipal_log_print(minipal_log_flags_info, __VA_ARGS__) +#define minipal_log_print_debug(...) minipal_log_print(minipal_log_flags_debug, __VA_ARGS__) +#define minipal_log_print_verbose(...) minipal_log_print(minipal_log_flags_verbose, __VA_ARGS__) +#define minipal_log_print_stderr(...) minipal_log_print(minipal_log_flags_stderr, __VA_ARGS__) +#define minipal_log_print_stdout(...) minipal_log_print(minipal_log_flags_stdout, __VA_ARGS__) +int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ); + +#define minipal_log_vprint_fatal(...) minipal_log_vprint(minipal_log_flags_fatal, __VA_ARGS__) +#define minipal_log_vprint_error(...) minipal_log_vprint(minipal_log_flags_error, __VA_ARGS__) +#define minipal_log_vprint_warning(...) minipal_log_vprint(minipal_log_flags_warning, __VA_ARGS__) +#define minipal_log_vprint_info(...) minipal_log_vprint(minipal_log_flags_info, __VA_ARGS__) +#define minipal_log_vprint_debug(...) minipal_log_vprint(minipal_log_flags_debug, __VA_ARGS__) +#define minipal_log_vprint_verbose(...) minipal_log_vprint(minipal_log_flags_verbose, __VA_ARGS__) +#define minipal_log_vprint_stderr(...) minipal_log_print(minipal_log_flags_stderr, __VA_ARGS__) +#define minipal_log_vprint_stdout(...) minipal_log_print(minipal_log_flags_stdout, __VA_ARGS__) +int minipal_log_vprint(minipal_log_flags flags, const char* fmt,va_list args); + +#define minipal_log_flush_fatal() minipal_log_flush(minipal_log_flags_fatal) +#define minipal_log_flush_error() minipal_log_flush(minipal_log_flags_error) +#define minipal_log_flush_warning() minipal_log_flush(minipal_log_flags_warning) +#define minipal_log_flush_info() minipal_log_flush(minipal_log_flags_info) +#define minipal_log_flush_debug() minipal_log_flush(minipal_log_flags_debug) +#define minipal_log_flush_verbose() minipal_log_flush(minipal_log_flags_verbose) +#define minipal_log_flush_stderr() minipal_log_flush(minipal_log_flags_stderr) +#define minipal_log_flush_stdout() minipal_log_flush(minipal_log_flags_stdout) +void minipal_log_flush(minipal_log_flags flags); + +// None crt, async safe log write. +#define minipal_log_write_fatal(msg) minipal_log_write(minipal_log_flags_fatal, msg) +#define minipal_log_write_error(msg) minipal_log_write(minipal_log_flags_error, msg) +#define minipal_log_write_warning(msg) minipal_log_write(minipal_log_flags_warning, msg) +#define minipal_log_write_info(msg) minipal_log_write(minipal_log_flags_info, msg) +#define minipal_log_write_debug(msg) minipal_log_write(minipal_log_flags_debug, msg) +#define minipal_log_write_verbose(msg) minipal_log_write(minipal_log_flags_verbose, msg) +#define minipal_log_write_stderr(msg) minipal_log_write(minipal_log_flags_stderr, msg) +#define minipal_log_write_stdout(msg) minipal_log_write(minipal_log_flags_stdout, msg) +int minipal_log_write(minipal_log_flags flags, const char* msg); + +// None crt, async safe log sync. +#define minipal_log_sync_fatal() minipal_log_sync(minipal_log_flags_fatal) +#define minipal_log_sync_error() minipal_log_sync(minipal_log_flags_error) +#define minipal_log_sync_warning() minipal_log_sync(minipal_log_flags_warning) +#define minipal_log_sync_info() minipal_log_sync(minipal_log_flags_info) +#define minipal_log_sync_debug() minipal_log_sync(minipal_log_flags_debug) +#define minipal_log_sync_verbose() minipal_log_sync(minipal_log_flags_verbose) +#define minipal_log_sync_stderr() minipal_log_sync(minipal_log_flags_stderr) +#define minipal_log_sync_stdout() minipal_log_sync(minipal_log_flags_stdout) +void minipal_log_sync(minipal_log_flags flags); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* HAVE_MINIPAL_LOG_H */ From dca219fbc8562084a8513460aab53286de123696 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Wed, 12 Mar 2025 16:52:11 +0100 Subject: [PATCH 02/14] Review feedback. --- src/coreclr/jit/error.cpp | 8 ++++++++ src/coreclr/vm/eepolicy.cpp | 22 +++++++++------------- src/coreclr/vm/excep.cpp | 14 ++++++-------- src/coreclr/vm/util.cpp | 33 +++++++++++++++++++++++++++++++++ src/coreclr/vm/util.hpp | 3 +++ src/native/minipal/log.c | 2 -- 6 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index fee244db7da366..d04585cef94965 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -320,9 +320,13 @@ int vflogf(FILE* file, const char* fmt, va_list args) if (fmt[0] == '\0') { if (file == procstdout()) + { minipal_log_flush_verbose(); + } else + { fflush(file); + } return 0; } @@ -336,9 +340,13 @@ int vflogf(FILE* file, const char* fmt, va_list args) } if (file == procstdout()) + { minipal_log_write_verbose(buffer); + } else + { fputs(&buffer[0], file); + } return written; } diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 96076690a5e8d0..1bc63994ba27a2 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -48,7 +48,7 @@ void SafeExitProcess(UINT exitCode, ShutdownCompleteAction sca = SCA_ExitProcess { _ASSERTE(!"Bad Exit value"); FAULT_NOT_FATAL(); // if we OOM we can simply give up - minipal_log_print_stderr("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); + minipal_log_print_stdout("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); DebugBreak(); } } @@ -235,8 +235,7 @@ class CallStackLogger TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature); str.Append(W("\n")); - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(strUTF8, str.GetUnicode(), CP_UTF8); - minipal_log_write_stderr(strUTF8); + PrintToStdErrW(str.GetUnicode()); } public: @@ -266,15 +265,14 @@ class CallStackLogger SmallStackSString repeatStr; repeatStr.AppendPrintf("Repeated %d times:\n", m_largestCommonStartRepeat); - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(repeatStrUTF8, repeatStr.GetUnicode(), CP_UTF8); - minipal_log_write_stderr(repeatStrUTF8); + PrintToStdErrW(repeatStr.GetUnicode()); - minipal_log_write_stderr("--------------------------------\n"); + PrintToStdErrA("--------------------------------\n"); for (int i = 0; i < m_largestCommonStartLength; i++) { PrintFrame(i, pWordAt); } - minipal_log_write_stderr("--------------------------------\n"); + PrintToStdErrA("--------------------------------\n"); } for (int i = m_largestCommonStartLength * m_largestCommonStartRepeat; i < m_frames.Count(); i++) @@ -360,7 +358,7 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS { if (previousThreadID == currentThreadID) { - minipal_log_write_stderr("Fatal error while logging another fatal error.\n"); + PrintToStdErrA("Fatal error while logging another fatal error.\n"); } else { @@ -405,8 +403,7 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS message.Append(W("\n")); - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(messageUTF8, message.GetUnicode(), CP_UTF8); - minipal_log_write_stderr(messageUTF8); + PrintToStdErrW(message.GetUnicode()); Thread* pThread = GetThreadNULLOk(); if (pThread && errorSource == NULL) @@ -414,8 +411,7 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS LogCallstackForLogWorker(pThread, pExceptionInfo); if (argExceptionString != NULL) { - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(argExceptionStringUTF8, argExceptionString, CP_UTF8); - minipal_log_write_stderr(argExceptionStringUTF8); + PrintToStdErrW(argExceptionString); } } } @@ -607,7 +603,7 @@ void DisplayStackOverflowException() { LIMITED_METHOD_CONTRACT; - minipal_log_write_stderr("Stack overflow.\n"); + PrintToStdErrA("Stack overflow.\n"); } DWORD LogStackOverflowStackTraceThread(void* arg) diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index e2c4564293768e..2bef68c8814e95 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4550,7 +4550,7 @@ lDone: ; char buffer[200]; sprintf_s(buffer, 200, "\nInternal error: Uncaught exception was thrown from IP = %p in UnhandledExceptionFilter_Worker on thread 0x%08x\n", param.ExceptionEIP, ((GetThreadNULLOk() == NULL) ? 0 : GetThread()->GetThreadId())); - minipal_log_write_stderr(buffer); + PrintToStdErrA(buffer); _ASSERTE(!"Unexpected exception in UnhandledExceptionFilter_Worker"); #endif EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE) @@ -4796,8 +4796,7 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, } message.Append(W("\n")); - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(messageUTF8, message.GetUnicode(), CP_UTF8); - minipal_log_write_stderr(messageUTF8); + PrintToStdErrW(message.GetUnicode()); #if defined(FEATURE_EVENT_TRACE) && !defined(TARGET_UNIX) // Send the log to Windows Event Log @@ -4979,11 +4978,11 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, if (IsOutOfMemory) { - minipal_log_write_stderr("Out of memory.\n"); + PrintToStdErrA("Out of memory.\n"); } else { - minipal_log_write_stderr("Stack overflow.\n"); + PrintToStdErrA("Stack overflow.\n"); } } else if (SentEvent || IsAsyncThreadException(&throwable)) @@ -5010,15 +5009,14 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, UtilLoadStringRC(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf + 4, buf_size - 6); wcscat_s(buf, buf_size, W("\n")); - MAKE_MULTIBYTE_FROMWIDE_BESTFIT(bufUTF8, buf, CP_UTF8); - minipal_log_write_stderr(bufUTF8); + PrintToStdErrW(buf); } EX_END_CATCH(SwallowAllExceptions); } EX_CATCH { // If we got here, we can't even print the localized error message. Print non-localized. LOG((LF_EH, LL_INFO10, "Exception occurred while logging processing uncaught exception\n")); - minipal_log_write_stderr("\n Error: Can't print exception string because Exception.ToString() failed.\n"); + PrintToStdErrA("\n Error: Can't print exception string because Exception.ToString() failed.\n"); } EX_END_CATCH(SwallowAllExceptions); } diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 8185f8780e791e..6d422e20c890e5 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -116,6 +116,39 @@ LPVOID CQuickHeap::Alloc(UINT sz) } } +//---------------------------------------------------------------------------- +// Output functions that avoid the crt's. +//---------------------------------------------------------------------------- + +void PrintToStdErrA(const char *pszString) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END + + minipal_log_write_stderr(pszString); +} + +void PrintToStdErrW(const WCHAR *pwzString) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + INJECT_FAULT(COMPlusThrowOM();); + } + CONTRACTL_END + + MAKE_MULTIBYTE_FROMWIDE_BESTFIT(pStr, pwzString, GetConsoleOutputCP()); + + PrintToStdErrA(pStr); +} +//---------------------------------------------------------------------------- + //***************************************************************************** // Compare VarLoc's //***************************************************************************** diff --git a/src/coreclr/vm/util.hpp b/src/coreclr/vm/util.hpp index 3c67f9bf6565cf..e4315c6181c272 100644 --- a/src/coreclr/vm/util.hpp +++ b/src/coreclr/vm/util.hpp @@ -189,6 +189,9 @@ class CQuickHeap QuickBlock *m_pFirstBigQuickBlock; }; +void PrintToStdErrA(const char *pszString); +void PrintToStdErrW(const WCHAR *pwzString); + #include "nativevaraccessors.h" // -------------------------------------------------------------------------------- diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index ea81a1fb391b43..9c233bbff79c3c 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -85,7 +85,6 @@ int minipal_log_vprint(minipal_log_flags flags, const char* fmt, va_list args) void minipal_log_flush(minipal_log_flags flags) { - ; } static size_t log_write_line(minipal_log_flags flags, const char* msg, size_t msg_len) @@ -155,7 +154,6 @@ int minipal_log_write(minipal_log_flags flags, const char* msg) void minipal_log_sync(minipal_log_flags flags) { - ; } #else #include From 0155fd69a91339c19ebbdda11339abf0c7ef4b49 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 13 Mar 2025 13:09:58 +0100 Subject: [PATCH 03/14] Fix minipal build under Mono. --- src/mono/CMakeLists.txt | 1 - src/mono/mono/CMakeLists.txt | 1 + src/mono/mono/minipal/CMakeLists.txt | 10 ++++++++++ src/native/minipal/guid.c | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/mono/mono/minipal/CMakeLists.txt diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index f0160b4974df59..834c4881aac512 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -882,7 +882,6 @@ endif() ### End of OS specific checks include_directories("${CLR_SRC_NATIVE_DIR}") -add_subdirectory(${CLR_SRC_NATIVE_DIR}/minipal minipal) if(NOT DISABLE_LIBS) set(INSTALL_MONO_API 1) diff --git a/src/mono/mono/CMakeLists.txt b/src/mono/mono/CMakeLists.txt index c59470996f5825..9368f312502d0e 100644 --- a/src/mono/mono/CMakeLists.txt +++ b/src/mono/mono/CMakeLists.txt @@ -1,6 +1,7 @@ project(mono) set(subdirs + minipal eglib utils sgen diff --git a/src/mono/mono/minipal/CMakeLists.txt b/src/mono/mono/minipal/CMakeLists.txt new file mode 100644 index 00000000000000..2b862bd623b3e3 --- /dev/null +++ b/src/mono/mono/minipal/CMakeLists.txt @@ -0,0 +1,10 @@ + +if (HOST_WIN32) + add_definitions(-DHOST_WINDOWS) +endif (HOST_WIN32) + +if (HOST_DARWIN OR HOST_ANDROID OR HOST_LINUX OR HOST_FREEBSD OR HOST_SOLARIS OR HOST_HAIKU OR HOST_BROWSER) + add_definitions(-DHOST_UNIX) +endif (HOST_DARWIN OR HOST_ANDROID OR HOST_LINUX OR HOST_FREEBSD OR HOST_SOLARIS OR HOST_HAIKU OR HOST_BROWSER) + +add_subdirectory(${CLR_SRC_NATIVE_DIR}/minipal minipal) diff --git a/src/native/minipal/guid.c b/src/native/minipal/guid.c index a3620c10783c3a..8169e738bb6acf 100644 --- a/src/native/minipal/guid.c +++ b/src/native/minipal/guid.c @@ -8,6 +8,7 @@ #include #ifdef HOST_WINDOWS #include +#include #endif // See RFC-4122 section 4.4 on creation of random GUID. From faf293b8e3bbe43e17815bf674acec4f2efac86d Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 13 Mar 2025 13:10:38 +0100 Subject: [PATCH 04/14] Use CLR_CMAKE_HOST_ANDROID instead of CLR_CMAKE_TARGET_ANDROID in CMake. --- src/native/minipal/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/minipal/CMakeLists.txt b/src/native/minipal/CMakeLists.txt index 18473da705d609..f27ad0d5fea50e 100644 --- a/src/native/minipal/CMakeLists.txt +++ b/src/native/minipal/CMakeLists.txt @@ -37,9 +37,9 @@ endif() add_library(minipal STATIC) target_link_libraries(minipal PRIVATE minipal_objects) -if(CLR_CMAKE_TARGET_ANDROID) +if(CLR_CMAKE_HOST_ANDROID) target_link_libraries(minipal PRIVATE log) -endif(CLR_CMAKE_TARGET_ANDROID) +endif(CLR_CMAKE_HOST_ANDROID) add_library(minipal_sanitizer_support OBJECT sansupport.c) From 18348934bb4471bd70bad209a22c50cc243348d2 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 13 Mar 2025 13:11:02 +0100 Subject: [PATCH 05/14] Reduce WIN32 API usage in log.c. --- src/native/minipal/log.c | 123 ++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 73 deletions(-) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index 9c233bbff79c3c..1993dd9b3a26e0 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -3,6 +3,7 @@ #include "log.h" #include +#include #ifndef MINIPAL_LOG_RUNTIME_TAG #define MINIPAL_LOG_RUNTIME_TAG "DOTNET" @@ -118,8 +119,7 @@ static size_t log_write_line(minipal_log_flags flags, const char* msg, size_t ms int minipal_log_write(minipal_log_flags flags, const char* msg) { - if (msg == NULL || msg[0] == '\0') - return 0; + assert(msg != NULL && msg[0] != '\0'); size_t msg_len = strlen(msg); const char* msg_end = msg + msg_len; @@ -156,6 +156,7 @@ void minipal_log_sync(minipal_log_flags flags) { } #else +#include #include #define MINIPAL_LOG_MAX_PAYLOAD 32767 @@ -197,103 +198,67 @@ void minipal_log_flush(minipal_log_flags flags) fflush(file); } -#if defined(HOST_WINDOWS) +#ifdef HOST_WINDOWS #include - -static HANDLE get_std_handle(minipal_log_flags flags) +#include +static int sync_file(minipal_log_flags flags) { switch(flags) { case minipal_log_flags_fatal: case minipal_log_flags_error: - return GetStdHandle(STD_ERROR_HANDLE); + FlushFileBuffers(GetStdHandle(STD_ERROR_HANDLE)); + break; case minipal_log_flags_warning: case minipal_log_flags_info: case minipal_log_flags_debug: case minipal_log_flags_verbose: default: - return GetStdHandle(STD_OUTPUT_HANDLE); + FlushFileBuffers(GetStdHandle(STD_OUTPUT_HANDLE)); + break; } -} -static size_t write_file(HANDLE handle, const char* msg, size_t bytes_to_write) + return 0; +} +#define fileno _fileno +#define write _write +#elif defined(__APPLE__) +#include +static int sync_file(minipal_log_flags flags) { - if (handle == INVALID_HANDLE_VALUE) - return 0; - - if (msg == NULL || msg[0] == '\0') + if (fcntl(fileno(get_std_file(flags))), F_FULLFSYNC) != -1) return 0; - DWORD bytes_written = 0; - if (!WriteFile(handle, msg, (DWORD)bytes_to_write, &bytes_written, NULL)) - bytes_written = 0; - - return bytes_written; + return errno; } - -static void sync_file(HANDLE handle) +#elif defined(HAVE_FSYNC) +#include +static int sync_file(minipal_log_flags flags) { - if (handle == INVALID_HANDLE_VALUE) - return; + if (fsync(fileno(get_std_file(flags))) == 0) + return 0; - FlushFileBuffers(handle); + return errno; } -#endif - -#if !defined(HOST_WINDOWS) -#include +#else #include -#include - -#define HANDLE int - -static HANDLE get_std_handle(minipal_log_flags flags) +static int sync_file(minipal_log_flags flags) { - return fileno(get_std_file(flags)); + sync(); + return 0; } +#endif -static int write_file(HANDLE handle, const char* msg, size_t bytes_to_write) +static int write_file(int fd, const char* msg, size_t bytes_to_write) { - if (handle == -1) + if (fd == -1) return 0; - if (msg == NULL || msg[0] == '\0') - return 0; - - return write(handle, msg, bytes_to_write); -} + assert(msg != NULL && msg[0] != '\0'); + assert(bytes_to_write < INT_MAX); -static void sync_file(HANDLE handle) -{ - if (handle == -1) - return; - - bool retry = false; -#if HAVE_FSYNC || defined(__APPLE__) - do - { -#if defined(__APPLE__) - if (fcntl(handle, F_FULLFSYNC) != -1) - break; -#else - if (fsync(handle) == 0) - break; -#endif - switch (errno) - { - case EINTR: - retry = true; - break; - default: - retry = false; - break; - } - } while (retry); -#else - sync(); -#endif + return write(fd, msg, (int)bytes_to_write); } -#endif int minipal_log_write(minipal_log_flags flags, const char* msg) { @@ -303,11 +268,11 @@ int minipal_log_write(minipal_log_flags flags, const char* msg) size_t bytes_to_write = strlen(msg); size_t bytes_written = 0; - HANDLE handle = get_std_handle(flags); + int fd = fileno(get_std_file(flags)); while (bytes_to_write > 0) { size_t chunk_to_write = bytes_to_write < MINIPAL_LOG_MAX_PAYLOAD ? bytes_to_write : MINIPAL_LOG_MAX_PAYLOAD; - size_t chunk_written = write_file(handle, msg, chunk_to_write); + size_t chunk_written = write_file(fd, msg, chunk_to_write); if (chunk_written == 0) break; @@ -322,6 +287,18 @@ int minipal_log_write(minipal_log_flags flags, const char* msg) void minipal_log_sync(minipal_log_flags flags) { - sync_file(get_std_handle(flags)); + bool retry = false; + do + { + switch (sync_file(flags)) + { + case EINTR: + retry = true; + break; + default: + retry = false; + break; + } + } while (retry); } #endif From 538a7be7d15ce0dd7668b028b4c1f190dc9598d6 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 13 Mar 2025 13:51:16 +0100 Subject: [PATCH 06/14] Reduce number of priority logging functions. --- src/coreclr/utilcode/log.cpp | 4 +-- src/coreclr/vm/eepolicy.cpp | 2 +- .../vm/eventing/eventpipe/ds-rt-coreclr.h | 8 +++--- src/coreclr/vm/util.cpp | 2 +- src/native/minipal/log.c | 20 +++++++++++++++ src/native/minipal/log.h | 25 ++----------------- 6 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/coreclr/utilcode/log.cpp b/src/coreclr/utilcode/log.cpp index e1c59408beb192..050fe4d64d1cb1 100644 --- a/src/coreclr/utilcode/log.cpp +++ b/src/coreclr/utilcode/log.cpp @@ -372,10 +372,10 @@ VOID LogSpewAlwaysValist(const char *fmt, va_list args) if (LogFlags & LOG_ENABLE_CONSOLE_LOGGING) { - minipal_log_write_stdout(pBuffer); + minipal_log_write_info(pBuffer); //@TODO ...Unnecessary to flush console? if (LogFlags & LOG_ENABLE_FLUSH_FILE) - minipal_log_sync_stdout(); + minipal_log_sync_info(); } if (LogFlags & LOG_ENABLE_DEBUGGER_LOGGING) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 1bc63994ba27a2..ae0f28796fd7db 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -48,7 +48,7 @@ void SafeExitProcess(UINT exitCode, ShutdownCompleteAction sca = SCA_ExitProcess { _ASSERTE(!"Bad Exit value"); FAULT_NOT_FATAL(); // if we OOM we can simply give up - minipal_log_print_stdout("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); + minipal_log_print_info("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); DebugBreak(); } } diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index e86b6c68b54252..2be358789efc59 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -405,10 +405,10 @@ ds_rt_server_log_pause_message (void) uint32_t port_suspended = ds_rt_config_value_get_default_port_suspend(); - minipal_log_print_stdout("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); - minipal_log_print_stdout("DOTNET_%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports); - minipal_log_print_stdout("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended); - minipal_log_flush_stdout(); + minipal_log_print_info("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); + minipal_log_print_info("DOTNET_%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports); + minipal_log_print_info("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended); + minipal_log_flush_info(); } #endif /* ENABLE_PERFTRACING */ diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 6d422e20c890e5..06216ef18fb9d8 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -130,7 +130,7 @@ void PrintToStdErrA(const char *pszString) } CONTRACTL_END - minipal_log_write_stderr(pszString); + minipal_log_write_error(pszString); } void PrintToStdErrW(const WCHAR *pwzString) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index 1993dd9b3a26e0..d6ec2301ece32d 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -88,6 +88,10 @@ void minipal_log_flush(minipal_log_flags flags) { } +void minipal_log_flush_all() +{ +} + static size_t log_write_line(minipal_log_flags flags, const char* msg, size_t msg_len) { char buffer[MINIPAL_LOG_MAX_PAYLOAD]; @@ -155,6 +159,10 @@ int minipal_log_write(minipal_log_flags flags, const char* msg) void minipal_log_sync(minipal_log_flags flags) { } + +void minipal_log_sync_all() +{ +} #else #include #include @@ -198,6 +206,12 @@ void minipal_log_flush(minipal_log_flags flags) fflush(file); } +void minipal_log_flush_all() +{ + minipal_log_flush(minipal_log_flags_error); + minipal_log_flush(minipal_log_flags_info); +} + #ifdef HOST_WINDOWS #include #include @@ -301,4 +315,10 @@ void minipal_log_sync(minipal_log_flags flags) } } while (retry); } + +void minipal_log_sync_all() +{ + minipal_log_sync(minipal_log_flags_error); + minipal_log_sync(minipal_log_flags_info); +} #endif diff --git a/src/native/minipal/log.h b/src/native/minipal/log.h index 33f0cb60c4a8cb..3307b7c5e29cd6 100644 --- a/src/native/minipal/log.h +++ b/src/native/minipal/log.h @@ -23,60 +23,39 @@ typedef enum minipal_log_flags_verbose = 1 << 6 } minipal_log_flags; -#define minipal_log_flags_stderr minipal_log_flags_error -#define minipal_log_flags_stdout minipal_log_flags_info - #define minipal_log_print_fatal(...) minipal_log_print(minipal_log_flags_fatal, __VA_ARGS__) #define minipal_log_print_error(...) minipal_log_print(minipal_log_flags_error, __VA_ARGS__) -#define minipal_log_print_warning(...) minipal_log_print(minipal_log_flags_warning, __VA_ARGS__) #define minipal_log_print_info(...) minipal_log_print(minipal_log_flags_info, __VA_ARGS__) -#define minipal_log_print_debug(...) minipal_log_print(minipal_log_flags_debug, __VA_ARGS__) #define minipal_log_print_verbose(...) minipal_log_print(minipal_log_flags_verbose, __VA_ARGS__) -#define minipal_log_print_stderr(...) minipal_log_print(minipal_log_flags_stderr, __VA_ARGS__) -#define minipal_log_print_stdout(...) minipal_log_print(minipal_log_flags_stdout, __VA_ARGS__) int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ); #define minipal_log_vprint_fatal(...) minipal_log_vprint(minipal_log_flags_fatal, __VA_ARGS__) #define minipal_log_vprint_error(...) minipal_log_vprint(minipal_log_flags_error, __VA_ARGS__) -#define minipal_log_vprint_warning(...) minipal_log_vprint(minipal_log_flags_warning, __VA_ARGS__) #define minipal_log_vprint_info(...) minipal_log_vprint(minipal_log_flags_info, __VA_ARGS__) -#define minipal_log_vprint_debug(...) minipal_log_vprint(minipal_log_flags_debug, __VA_ARGS__) #define minipal_log_vprint_verbose(...) minipal_log_vprint(minipal_log_flags_verbose, __VA_ARGS__) -#define minipal_log_vprint_stderr(...) minipal_log_print(minipal_log_flags_stderr, __VA_ARGS__) -#define minipal_log_vprint_stdout(...) minipal_log_print(minipal_log_flags_stdout, __VA_ARGS__) int minipal_log_vprint(minipal_log_flags flags, const char* fmt,va_list args); #define minipal_log_flush_fatal() minipal_log_flush(minipal_log_flags_fatal) #define minipal_log_flush_error() minipal_log_flush(minipal_log_flags_error) -#define minipal_log_flush_warning() minipal_log_flush(minipal_log_flags_warning) #define minipal_log_flush_info() minipal_log_flush(minipal_log_flags_info) -#define minipal_log_flush_debug() minipal_log_flush(minipal_log_flags_debug) #define minipal_log_flush_verbose() minipal_log_flush(minipal_log_flags_verbose) -#define minipal_log_flush_stderr() minipal_log_flush(minipal_log_flags_stderr) -#define minipal_log_flush_stdout() minipal_log_flush(minipal_log_flags_stdout) void minipal_log_flush(minipal_log_flags flags); +void minipal_log_flush_all(); // None crt, async safe log write. #define minipal_log_write_fatal(msg) minipal_log_write(minipal_log_flags_fatal, msg) #define minipal_log_write_error(msg) minipal_log_write(minipal_log_flags_error, msg) -#define minipal_log_write_warning(msg) minipal_log_write(minipal_log_flags_warning, msg) #define minipal_log_write_info(msg) minipal_log_write(minipal_log_flags_info, msg) -#define minipal_log_write_debug(msg) minipal_log_write(minipal_log_flags_debug, msg) #define minipal_log_write_verbose(msg) minipal_log_write(minipal_log_flags_verbose, msg) -#define minipal_log_write_stderr(msg) minipal_log_write(minipal_log_flags_stderr, msg) -#define minipal_log_write_stdout(msg) minipal_log_write(minipal_log_flags_stdout, msg) int minipal_log_write(minipal_log_flags flags, const char* msg); // None crt, async safe log sync. #define minipal_log_sync_fatal() minipal_log_sync(minipal_log_flags_fatal) #define minipal_log_sync_error() minipal_log_sync(minipal_log_flags_error) -#define minipal_log_sync_warning() minipal_log_sync(minipal_log_flags_warning) #define minipal_log_sync_info() minipal_log_sync(minipal_log_flags_info) -#define minipal_log_sync_debug() minipal_log_sync(minipal_log_flags_debug) #define minipal_log_sync_verbose() minipal_log_sync(minipal_log_flags_verbose) -#define minipal_log_sync_stderr() minipal_log_sync(minipal_log_flags_stderr) -#define minipal_log_sync_stdout() minipal_log_sync(minipal_log_flags_stdout) void minipal_log_sync(minipal_log_flags flags); +void minipal_log_sync_all(); #ifdef __cplusplus } From 119900c4828663c3fc1cf9767536f7c51a06894e Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 13 Mar 2025 17:35:15 +0100 Subject: [PATCH 07/14] Replaced one more if check with assert. --- src/native/minipal/log.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index d6ec2301ece32d..a9f3a9000a5ce3 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -276,8 +276,7 @@ static int write_file(int fd, const char* msg, size_t bytes_to_write) int minipal_log_write(minipal_log_flags flags, const char* msg) { - if (msg == NULL || msg[0] == '\0') - return 0; + assert(msg != NULL && msg[0] != '\0'); size_t bytes_to_write = strlen(msg); size_t bytes_written = 0; From 66360146f708111a62a260ad49bbde6b83bf4317 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 13 Mar 2025 17:43:10 +0100 Subject: [PATCH 08/14] Fix info -> error logging in SafeExitProcess. --- src/coreclr/vm/eepolicy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index ae0f28796fd7db..f1bfc42acecd8f 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -48,7 +48,7 @@ void SafeExitProcess(UINT exitCode, ShutdownCompleteAction sca = SCA_ExitProcess { _ASSERTE(!"Bad Exit value"); FAULT_NOT_FATAL(); // if we OOM we can simply give up - minipal_log_print_info("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); + minipal_log_print_error("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); DebugBreak(); } } From e941406375277683f449716cdfaa6f0629351e71 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Fri, 14 Mar 2025 09:28:22 +0100 Subject: [PATCH 09/14] Fix build error. --- src/native/minipal/log.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index a9f3a9000a5ce3..7171998a32433e 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -3,6 +3,7 @@ #include "log.h" #include +#include #include #ifndef MINIPAL_LOG_RUNTIME_TAG @@ -238,9 +239,10 @@ static int sync_file(minipal_log_flags flags) #define write _write #elif defined(__APPLE__) #include +#include static int sync_file(minipal_log_flags flags) { - if (fcntl(fileno(get_std_file(flags))), F_FULLFSYNC) != -1) + if (fcntl(fileno(get_std_file(flags)), F_FULLFSYNC) != -1) return 0; return errno; From 247b248ff54723f03ce334132cf965e8a081cbfb Mon Sep 17 00:00:00 2001 From: lateralusX Date: Fri, 14 Mar 2025 09:28:38 +0100 Subject: [PATCH 10/14] Apply JIT format patch. --- src/coreclr/jit/ee_il_dll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index f954ca6e90592f..9df0a0c29e56be 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -148,7 +148,7 @@ FILE* jitstdout() // Like printf/logf, but only outputs to jitstdout -- skips call back into EE. int jitprintf(const char* fmt, ...) { - int status; + int status; va_list vl; va_start(vl, fmt); if (jitstdout() == procstdout()) From a0ab79892410f4850d1aaaa5659952915324f4ce Mon Sep 17 00:00:00 2001 From: lateralusX Date: Fri, 14 Mar 2025 10:20:22 +0100 Subject: [PATCH 11/14] Fix issues on builds using -Werror,-Wstrict-prototypes. --- src/native/minipal/log.c | 8 ++++---- src/native/minipal/log.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index 7171998a32433e..06075f14c87b6e 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -89,7 +89,7 @@ void minipal_log_flush(minipal_log_flags flags) { } -void minipal_log_flush_all() +void minipal_log_flush_all(void) { } @@ -161,7 +161,7 @@ void minipal_log_sync(minipal_log_flags flags) { } -void minipal_log_sync_all() +void minipal_log_sync_all(void) { } #else @@ -207,7 +207,7 @@ void minipal_log_flush(minipal_log_flags flags) fflush(file); } -void minipal_log_flush_all() +void minipal_log_flush_all(void) { minipal_log_flush(minipal_log_flags_error); minipal_log_flush(minipal_log_flags_info); @@ -317,7 +317,7 @@ void minipal_log_sync(minipal_log_flags flags) } while (retry); } -void minipal_log_sync_all() +void minipal_log_sync_all(void) { minipal_log_sync(minipal_log_flags_error); minipal_log_sync(minipal_log_flags_info); diff --git a/src/native/minipal/log.h b/src/native/minipal/log.h index 3307b7c5e29cd6..e23b3efd4598d7 100644 --- a/src/native/minipal/log.h +++ b/src/native/minipal/log.h @@ -40,7 +40,7 @@ int minipal_log_vprint(minipal_log_flags flags, const char* fmt,va_list args); #define minipal_log_flush_info() minipal_log_flush(minipal_log_flags_info) #define minipal_log_flush_verbose() minipal_log_flush(minipal_log_flags_verbose) void minipal_log_flush(minipal_log_flags flags); -void minipal_log_flush_all(); +void minipal_log_flush_all(void); // None crt, async safe log write. #define minipal_log_write_fatal(msg) minipal_log_write(minipal_log_flags_fatal, msg) @@ -55,7 +55,7 @@ int minipal_log_write(minipal_log_flags flags, const char* msg); #define minipal_log_sync_info() minipal_log_sync(minipal_log_flags_info) #define minipal_log_sync_verbose() minipal_log_sync(minipal_log_flags_verbose) void minipal_log_sync(minipal_log_flags flags); -void minipal_log_sync_all(); +void minipal_log_sync_all(void); #ifdef __cplusplus } From 9875a37857ff37e592b69d24b56cc61efdada0ea Mon Sep 17 00:00:00 2001 From: lateralusX Date: Mon, 17 Mar 2025 09:45:06 +0100 Subject: [PATCH 12/14] Add ability to detect fsync availablilty in minipal. --- src/native/minipal/configure.cmake | 12 +++++------- src/native/minipal/log.c | 3 ++- src/native/minipal/minipalconfig.h.in | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/native/minipal/configure.cmake b/src/native/minipal/configure.cmake index 8a5dd2346a0e02..448b03ba7a250c 100644 --- a/src/native/minipal/configure.cmake +++ b/src/native/minipal/configure.cmake @@ -2,18 +2,16 @@ include(CheckFunctionExists) include(CheckIncludeFiles) include(CheckSymbolExists) +check_include_files("windows.h" HAVE_WINDOWS_H) +check_include_files("windows.h;bcrypt.h" HAVE_BCRYPT_H) check_include_files("sys/auxv.h;asm/hwcap.h" HAVE_AUXV_HWCAP_H) + check_function_exists(sysctlbyname HAVE_SYSCTLBYNAME) +check_function_exists(fsync HAVE_FSYNC) check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM_BUF) check_symbol_exists(O_CLOEXEC fcntl.h HAVE_O_CLOEXEC) -check_include_files("windows.h" HAVE_WINDOWS_H) -check_include_files("windows.h;bcrypt.h" HAVE_BCRYPT_H) - -check_symbol_exists( - clock_gettime_nsec_np - time.h - HAVE_CLOCK_GETTIME_NSEC_NP) +check_symbol_exists(clock_gettime_nsec_np time.h HAVE_CLOCK_GETTIME_NSEC_NP) if(CMAKE_C_BYTE_ORDER STREQUAL "BIG_ENDIAN") set(BIGENDIAN 1) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index 06075f14c87b6e..4418dfc9deba57 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include "minipalconfig.h" #include "log.h" #include #include @@ -247,7 +248,7 @@ static int sync_file(minipal_log_flags flags) return errno; } -#elif defined(HAVE_FSYNC) +#elif HAVE_FSYNC #include static int sync_file(minipal_log_flags flags) { diff --git a/src/native/minipal/minipalconfig.h.in b/src/native/minipal/minipalconfig.h.in index 00764722ef1b86..7310b2f6962cd9 100644 --- a/src/native/minipal/minipalconfig.h.in +++ b/src/native/minipal/minipalconfig.h.in @@ -9,5 +9,6 @@ #cmakedefine01 BIGENDIAN #cmakedefine01 HAVE_BCRYPT_H #cmakedefine01 HAVE_WINDOWS_H +#cmakedefine01 HAVE_FSYNC #endif From 44366aed6ece16defc3b5b7a61452e053c0026fb Mon Sep 17 00:00:00 2001 From: lateralusX Date: Wed, 19 Mar 2025 17:44:54 +0100 Subject: [PATCH 13/14] Review feedback. --- src/coreclr/utilcode/log.cpp | 1 - src/coreclr/vm/eepolicy.cpp | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/coreclr/utilcode/log.cpp b/src/coreclr/utilcode/log.cpp index 050fe4d64d1cb1..b95523fc33a218 100644 --- a/src/coreclr/utilcode/log.cpp +++ b/src/coreclr/utilcode/log.cpp @@ -373,7 +373,6 @@ VOID LogSpewAlwaysValist(const char *fmt, va_list args) if (LogFlags & LOG_ENABLE_CONSOLE_LOGGING) { minipal_log_write_info(pBuffer); - //@TODO ...Unnecessary to flush console? if (LogFlags & LOG_ENABLE_FLUSH_FILE) minipal_log_sync_info(); } diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index f1bfc42acecd8f..145e8e75461ff0 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -373,7 +373,7 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS EX_TRY { - SString message; + StackSString message; if (exitCode == (UINT)COR_E_FAILFAST) { message.Append(W("Process terminated. ")); @@ -387,6 +387,10 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS { message.Append(errorSource); message.Append(W("\n")); + + PrintToStdErrW(message.GetUnicode()); + + message.Clear(); } if (pszMessage != NULL) @@ -396,7 +400,7 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS else { // If no message was passed in, generate it from the exitCode - SString exitCodeMessage; + InlineSString<256> exitCodeMessage; GetHRMsg(exitCode, exitCodeMessage); message.Append(exitCodeMessage); } From 0d2a29ee69079ea5221d3edf5c48cd53703f3d09 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Thu, 20 Mar 2025 16:38:53 +0100 Subject: [PATCH 14/14] Make Android logcat logging ignore single '\n' log line. --- src/coreclr/vm/eepolicy.cpp | 21 +++++++-------------- src/native/minipal/log.c | 3 +++ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 145e8e75461ff0..b3f4a568a6696f 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -373,41 +373,34 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS EX_TRY { - StackSString message; if (exitCode == (UINT)COR_E_FAILFAST) { - message.Append(W("Process terminated. ")); + PrintToStdErrA("Process terminated.\n"); } else { - message.Append(W("Fatal error. ")); + PrintToStdErrA("Fatal error.\n"); } if (errorSource != NULL) { - message.Append(errorSource); - message.Append(W("\n")); - - PrintToStdErrW(message.GetUnicode()); - - message.Clear(); + PrintToStdErrW(errorSource); + PrintToStdErrA("\n"); } if (pszMessage != NULL) { - message.Append(pszMessage); + PrintToStdErrW(pszMessage); } else { // If no message was passed in, generate it from the exitCode InlineSString<256> exitCodeMessage; GetHRMsg(exitCode, exitCodeMessage); - message.Append(exitCodeMessage); + PrintToStdErrW(exitCodeMessage.GetUnicode()); } - message.Append(W("\n")); - - PrintToStdErrW(message.GetUnicode()); + PrintToStdErrA("\n"); Thread* pThread = GetThreadNULLOk(); if (pThread && errorSource == NULL) diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index 4418dfc9deba57..29ff23262e7676 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -46,6 +46,9 @@ static int android_log_flag(minipal_log_flags flags) static size_t log_write(minipal_log_flags flags, const char* msg, size_t msg_len) { + if (msg_len == 1 && msg[0] == '\n') + return 0; + return __android_log_write(android_log_flag(flags), MINIPAL_LOG_RUNTIME_TAG, msg) == 1 ? msg_len : 0; }