Skip to content

Initial CoreClr Android logcat log integration. #113416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/inc/utilcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ using std::nothrow;

#include <stddef.h>
#include <minipal/guid.h>
#include <minipal/log.h>
#include <dn-u16.h>

#include "clrnt.h"
Expand Down
21 changes: 11 additions & 10 deletions src/coreclr/jit/ee_il_dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#define DLLEXPORT
#endif // !DLLEXPORT

#if defined(HOST_ANDROID)
#include <android/log.h>
#endif
#include "minipal/log.h"

/*****************************************************************************/

Expand Down Expand Up @@ -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;
}

Expand Down
21 changes: 18 additions & 3 deletions src/coreclr/jit/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#pragma hdrstop
#endif
#include "compiler.h"
#include "minipal/log.h"

#if MEASURE_FATAL
unsigned fatal_badCode;
Expand Down Expand Up @@ -318,7 +319,14 @@ 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;
}

Expand All @@ -331,8 +339,15 @@ 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;
}

Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2452,6 +2452,16 @@ PAL_GenerateCoreDump(

(no return value)
--*/
#ifdef HOST_ANDROID
#include <minipal/log.h>
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)
{
Expand Down Expand Up @@ -2520,6 +2530,7 @@ PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize)
free(signalAddressArg);
}
}
#endif

/*++
Function:
Expand Down
6 changes: 2 additions & 4 deletions src/coreclr/utilcode/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,9 @@ VOID LogSpewAlwaysValist(const char *fmt, va_list args)

if (LogFlags & LOG_ENABLE_CONSOLE_LOGGING)
{
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pBuffer, buflen, &written, 0);
//<TODO>@TODO ...Unnecessary to flush console?</TODO>
minipal_log_write_info(pBuffer);
if (LogFlags & LOG_ENABLE_FLUSH_FILE)
FlushFileBuffers( GetStdHandle(STD_OUTPUT_HANDLE) );
minipal_log_sync_info();
}

if (LogFlags & LOG_ENABLE_DEBUGGER_LOGGING)
Expand Down Expand Up @@ -415,6 +414,5 @@ VOID LogSpewAlways (const char *fmt, ... )
LogSpewValist (LF_ALWAYS, LL_ALWAYS, fmt, args);
va_end(args);
}

#endif // LOGGING

14 changes: 8 additions & 6 deletions src/coreclr/vm/eepolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_error("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode);
DebugBreak();
}
}
Expand Down Expand Up @@ -233,8 +233,9 @@ class CallStackLogger

MethodDesc* pMD = m_frames[index];
TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature);
str.Append(W("\n"));

PrintToStdErrW(str.GetUnicode());
PrintToStdErrA("\n");
}

public:
Expand Down Expand Up @@ -265,6 +266,7 @@ class CallStackLogger
repeatStr.AppendPrintf("Repeated %d times:\n", m_largestCommonStartRepeat);

PrintToStdErrW(repeatStr.GetUnicode());

PrintToStdErrA("--------------------------------\n");
for (int i = 0; i < m_largestCommonStartLength; i++)
{
Expand Down Expand Up @@ -373,11 +375,11 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS
{
if (exitCode == (UINT)COR_E_FAILFAST)
{
PrintToStdErrA("Process terminated. ");
PrintToStdErrA("Process terminated.\n");
}
else
{
PrintToStdErrA("Fatal error. ");
PrintToStdErrA("Fatal error.\n");
}

if (errorSource != NULL)
Expand All @@ -393,9 +395,9 @@ 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);
PrintToStdErrW((LPCWSTR)exitCodeMessage);
PrintToStdErrW(exitCodeMessage.GetUnicode());
}

PrintToStdErrA("\n");
Expand Down
9 changes: 5 additions & 4 deletions src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "ep-rt-coreclr.h"
#include <clrconfignocache.h>
#include <generatedumpflags.h>
#include <minipal/log.h>
#include <eventpipe/ds-process-protocol.h>
#include <eventpipe/ds-profiler-protocol.h>
#include <eventpipe/ds-dump-protocol.h>
Expand Down Expand Up @@ -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_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 */
Expand Down
25 changes: 13 additions & 12 deletions src/coreclr/vm/excep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -4788,17 +4786,17 @@ 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");
PrintToStdErrW(message.GetUnicode());

#if defined(FEATURE_EVENT_TRACE) && !defined(TARGET_UNIX)
// Send the log to Windows Event Log
Expand Down Expand Up @@ -5005,10 +5003,13 @@ 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 ");

_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"));

PrintToStdErrW(buf);
PrintToStdErrA("\n");
}
EX_END_CATCH(SwallowAllExceptions);
}
Expand Down
60 changes: 2 additions & 58 deletions src/coreclr/vm/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@

#ifndef DACCESS_COMPILE

#if defined(TARGET_ANDROID)
#include <android/log.h>
#endif // defined(TARGET_ANDROID)

thread_local size_t t_ThreadType;

void ClrFlsSetThreadType(TlsThreadTypeFlag flag)
Expand Down Expand Up @@ -124,8 +120,7 @@ LPVOID CQuickHeap::Alloc(UINT sz)
// Output functions that avoid the crt's.
//----------------------------------------------------------------------------

static
void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite)
void PrintToStdErrA(const char *pszString)
{
CONTRACTL
{
Expand All @@ -135,58 +130,7 @@ void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite)
}
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)
minipal_log_write_error(pszString);
}

void PrintToStdErrW(const WCHAR *pwzString)
Expand Down
1 change: 0 additions & 1 deletion src/mono/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
project(mono)

set(subdirs
minipal
eglib
utils
sgen
Expand Down
10 changes: 10 additions & 0 deletions src/mono/mono/minipal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
5 changes: 5 additions & 0 deletions src/native/minipal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,6 +37,10 @@ endif()
add_library(minipal STATIC)
target_link_libraries(minipal PRIVATE minipal_objects)

if(CLR_CMAKE_HOST_ANDROID)
target_link_libraries(minipal PRIVATE log)
endif(CLR_CMAKE_HOST_ANDROID)

add_library(minipal_sanitizer_support OBJECT
sansupport.c)
# Exclude this target from the default build as we may not have sanitzer headers available
Expand Down
Loading
Loading