From 35f104c141d30228c435f679fd9142e7076c1588 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Tue, 13 Jun 2023 09:39:18 -0700 Subject: [PATCH 1/9] initial changes for process name --- .../nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | 44 +++++++++++++++++-- .../eventpipe/processinfo/processinfo.cs | 4 +- .../eventpipe/processinfo/processinfo.csproj | 2 + .../eventpipe/processinfo2/processinfo2.cs | 4 +- .../processinfo2/processinfo2.csproj | 2 + 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index f7793b4065f535..5cab0a06089fb3 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -11,6 +11,7 @@ #ifdef TARGET_WINDOWS #include +#include #else #include #include @@ -41,7 +42,6 @@ thread_local EventPipeAotThreadHolderTLS EventPipeAotThreadHolderTLS::g_threadHo ep_rt_lock_handle_t _ep_rt_aot_config_lock_handle; CrstStatic _ep_rt_aot_config_lock; -ep_char8_t *volatile _ep_rt_aot_diagnostics_cmd_line; #ifndef TARGET_UNIX uint32_t *_ep_rt_aot_proc_group_offsets; @@ -85,12 +85,39 @@ ep_rt_aot_sample_profiler_write_sampling_event_for_threads ( { } +#if defined (__linux__) +extern char *__progname; +#endif + const ep_char8_t * ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) { - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: Implement EventPipe assembly name - return filename in nativeaot? +#ifdef HOST_WINDOWS + ep_char8_t *buffer = reinterpret_cast(malloc(MAX_PATH)); + GetProcessImageFileNameA(GetCurrentProcess(), buffer, MAX_PATH); + char* process_name = (strrchr(buffer, '\\') + 1); + if (process_name != NULL) + { + char* extension = strrchr(process_name, '.'); + if (extension != NULL) + { + *extension = '\0'; + } + return reinterpret_cast(process_name); + } return reinterpret_cast(""); +#else +#if defined (__linux__) + char *process_name = __progname; + char *dot = strrchr(process_name, '.'); + if (dot != NULL) { + *dot = '\0'; + } + return reinterpret_cast(process_name); +#else + return reinterpret_cast(""); +#endif +#endif // HOST_WINDOWS } const ep_char8_t * @@ -101,6 +128,17 @@ ep_rt_aot_diagnostics_command_line_get (void) #ifdef TARGET_WINDOWS const ep_char16_t* command_line = reinterpret_cast(::GetCommandLineW()); return ep_rt_utf16_to_utf8_string(command_line, -1); +#elif TARGET_LINUX + FILE *cmdline_file = ::fopen("/proc/self/cmdline", "r"); + if (cmdline_file == nullptr) + return ""; + + char *line = NULL; + size_t line_len = 0; + if (::getline (&line, &line_len, cmdline_file) == -1) + return ""; + + return reinterpret_cast(line); #else return ""; #endif diff --git a/src/tests/tracing/eventpipe/processinfo/processinfo.cs b/src/tests/tracing/eventpipe/processinfo/processinfo.cs index a62865bf2dff87..5efe95aee8300b 100644 --- a/src/tests/tracing/eventpipe/processinfo/processinfo.cs +++ b/src/tests/tracing/eventpipe/processinfo/processinfo.cs @@ -149,7 +149,9 @@ public static int Main() // /path/to/corerun /path/to/processinfo.dll // or // "C:\path\to\CoreRun.exe" C:\path\to\processinfo.dll - string currentProcessCommandLine = $"{currentProcess.MainModule.FileName} {System.Reflection.Assembly.GetExecutingAssembly().Location}"; + string currentProcessCommandLine = TestLibrary.Utilities.IsNativeAot + ? currentProcess.MainModule.FileName + : $"{currentProcess.MainModule.FileName} {System.Reflection.Assembly.GetExecutingAssembly().Location}"; string receivedCommandLine = NormalizeCommandLine(commandLine); Utils.Assert(currentProcessCommandLine.Equals(receivedCommandLine, StringComparison.OrdinalIgnoreCase), $"CommandLine must match current process. Expected: {currentProcessCommandLine}, Received: {receivedCommandLine} (original: {commandLine})"); } diff --git a/src/tests/tracing/eventpipe/processinfo/processinfo.csproj b/src/tests/tracing/eventpipe/processinfo/processinfo.csproj index d4947c794dcebe..573d94f3a149ea 100644 --- a/src/tests/tracing/eventpipe/processinfo/processinfo.csproj +++ b/src/tests/tracing/eventpipe/processinfo/processinfo.csproj @@ -11,9 +11,11 @@ Issue: https://github.com/dotnet/runtime/issues/39935 --> true + true + diff --git a/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs b/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs index 0c04dd3caef877..472392ecfb082a 100644 --- a/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs +++ b/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs @@ -150,7 +150,9 @@ public static int Main() // /path/to/corerun /path/to/processinfo.dll // or // "C:\path\to\CoreRun.exe" C:\path\to\processinfo.dll - string currentProcessCommandLine = $"{currentProcess.MainModule.FileName} {System.Reflection.Assembly.GetExecutingAssembly().Location}"; + string currentProcessCommandLine = TestLibrary.Utilities.IsNativeAot + ? currentProcess.MainModule.FileName + : $"{currentProcess.MainModule.FileName} {System.Reflection.Assembly.GetExecutingAssembly().Location}"; string receivedCommandLine = NormalizeCommandLine(commandLine); Utils.Assert(currentProcessCommandLine.Equals(receivedCommandLine, StringComparison.OrdinalIgnoreCase), $"CommandLine must match current process. Expected: {currentProcessCommandLine}, Received: {receivedCommandLine} (original: {commandLine})"); } diff --git a/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj b/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj index d4947c794dcebe..573d94f3a149ea 100644 --- a/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj +++ b/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj @@ -11,9 +11,11 @@ Issue: https://github.com/dotnet/runtime/issues/39935 --> true + true + From 0ebec81f3401b194bcf28117adee07f6a66ce643 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Wed, 14 Jun 2023 09:39:15 -0700 Subject: [PATCH 2/9] add support to get managedEntrypointAssemblyName --- eng/pipelines/runtime.yml | 2 +- .../nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | 80 +++++++++++++------ 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 52c5547c47b4b2..13cc33d5346fe6 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -248,7 +248,7 @@ extends: extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml extraStepsParameters: creator: dotnet-bot - testBuildArgs: 'nativeaot tree ";nativeaot;Loader;Interop;tracing/eventpipe/config;tracing/eventpipe/diagnosticport;tracing/eventpipe/reverse;" test tracing/eventcounter/runtimecounters.csproj /p:BuildNativeAotFrameworkObjects=true' + testBuildArgs: 'nativeaot tree ";nativeaot;Loader;Interop;tracing/eventpipe/config;tracing/eventpipe/diagnosticport;tracing/eventpipe/reverse;tracing/eventpipe/processinfo2;" test tracing/eventcounter/runtimecounters.csproj /p:BuildNativeAotFrameworkObjects=true' liveLibrariesBuildConfig: Release testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig) extraVariablesTemplates: diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index 5cab0a06089fb3..350094437d2cc1 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -11,7 +11,6 @@ #ifdef TARGET_WINDOWS #include -#include #else #include #include @@ -92,32 +91,61 @@ extern char *__progname; const ep_char8_t * ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) { + // Although PalGetModuleFileName exists, non-windows implementation has issues and we use __progname for Linux. + // Cannot use __cpp_threadsafe_static_init feature since it will bring in the C++ runtime and need to use threadsafe way to initialize entrypoint_assembly_name + static const ep_char8_t * entrypoint_assembly_name = nullptr; + if (entrypoint_assembly_name == nullptr) { + const ep_char8_t * entrypoint_assembly_name_local; #ifdef HOST_WINDOWS - ep_char8_t *buffer = reinterpret_cast(malloc(MAX_PATH)); - GetProcessImageFileNameA(GetCurrentProcess(), buffer, MAX_PATH); - char* process_name = (strrchr(buffer, '\\') + 1); - if (process_name != NULL) - { - char* extension = strrchr(process_name, '.'); - if (extension != NULL) - { - *extension = '\0'; + const TCHAR * wszModuleFileName = NULL; + if(PalGetModuleFileName(&wszModuleFileName, nullptr) == 0) + entrypoint_assembly_name_local = reinterpret_cast(""); + else { + const wchar_t* process_name = wcsrchr(wszModuleFileName, '\\'); + if (process_name != NULL) { + const wchar_t* extension = wcschr(process_name + 1, '.'); + if (extension != NULL) { + // We don't want to include the first '\' + size_t len = extension - (process_name + 1); + wchar_t* process_name_wo_ext = reinterpret_cast(malloc(len + 1)); + wcsncpy(process_name_wo_ext, process_name + 1, len); + process_name_wo_ext[len] = L'\0'; + const ep_char16_t* process_name_wo_ext_l = reinterpret_cast(process_name_wo_ext); + entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_wo_ext_l, -1); + } else { + const ep_char16_t* process_name_l = reinterpret_cast(process_name + 1); + entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_l, -1); + } + } + else + entrypoint_assembly_name_local = reinterpret_cast(""); } - return reinterpret_cast(process_name); - } - return reinterpret_cast(""); #else #if defined (__linux__) - char *process_name = __progname; - char *dot = strrchr(process_name, '.'); - if (dot != NULL) { - *dot = '\0'; + size_t program_len = strlen(__progname); + ep_char8_t *process_name = reinterpret_cast(malloc(program_len + 1)); + if (process_name == NULL) + entrypoint_assembly_name_local = reinterpret_cast(""); + else { + memcpy (process_name, __progname, program_len); + process_name[program_len] = '\0'; + char *dot = strrchr(process_name, '.'); + if (dot != NULL) { + *dot = '\0'; + } + entrypoint_assembly_name_local = reinterpret_cast(process_name); } - return reinterpret_cast(process_name); #else - return reinterpret_cast(""); -#endif + entrypoint_assembly_name_local = reinterpret_cast(""); +#endif // __linux__ #endif // HOST_WINDOWS + + if (PalInterlockedCompareExchangePointer((void**)(&entrypoint_assembly_name), (void*)(entrypoint_assembly_name_local), nullptr) != nullptr) + { + delete[] entrypoint_assembly_name_local; + } + } + return reinterpret_cast(entrypoint_assembly_name); } const ep_char8_t * @@ -426,10 +454,10 @@ ep_rt_aot_file_close (ep_rt_file_handle_t file_handle) bool ep_rt_aot_file_write ( - ep_rt_file_handle_t file_handle, - const uint8_t *buffer, - uint32_t bytes_to_write, - uint32_t *bytes_written) + ep_rt_file_handle_t file_handle, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) { #ifdef TARGET_WINDOWS return ::WriteFile (file_handle, buffer, bytes_to_write, reinterpret_cast(bytes_written), NULL) != FALSE; @@ -722,12 +750,12 @@ void ep_rt_aot_lock_requires_lock_not_held (const ep_rt_lock_handle_t *lock) void ep_rt_aot_spin_lock_requires_lock_held (const ep_rt_spin_lock_handle_t *spin_lock) { EP_ASSERT (ep_rt_spin_lock_is_valid (spin_lock)); - EP_ASSERT (spin_lock->lock->OwnedByCurrentThread ()); + EP_ASSERT (spin_lock->lock->OwnedByCurrentThread ()); } void ep_rt_aot_spin_lock_requires_lock_not_held (const ep_rt_spin_lock_handle_t *spin_lock) { - EP_ASSERT (spin_lock->lock == NULL || !spin_lock->lock->OwnedByCurrentThread ()); + EP_ASSERT (spin_lock->lock == NULL || !spin_lock->lock->OwnedByCurrentThread ()); } #endif /* EP_CHECKED_BUILD */ From f768b69854a1306791bb765a72d411da78f55e91 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Wed, 14 Jun 2023 16:03:52 -0700 Subject: [PATCH 3/9] FB --- src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | 7 ++++--- .../tracing/eventpipe/diagnosticport/diagnosticport.cs | 7 +++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index 350094437d2cc1..fcb61af259b578 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -141,9 +141,7 @@ ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) #endif // HOST_WINDOWS if (PalInterlockedCompareExchangePointer((void**)(&entrypoint_assembly_name), (void*)(entrypoint_assembly_name_local), nullptr) != nullptr) - { delete[] entrypoint_assembly_name_local; - } } return reinterpret_cast(entrypoint_assembly_name); } @@ -163,9 +161,12 @@ ep_rt_aot_diagnostics_command_line_get (void) char *line = NULL; size_t line_len = 0; - if (::getline (&line, &line_len, cmdline_file) == -1) + if (::getline (&line, &line_len, cmdline_file) == -1) { + ::fclose (cmdline_file); return ""; + } + ::fclose (cmdline_file); return reinterpret_cast(line); #else return ""; diff --git a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs index a1c08d4f1b9f55..7e2edfc3896fe4 100644 --- a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs +++ b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs @@ -403,10 +403,9 @@ public static async Task TEST_CanGetProcessInfo2WhileSuspended() } else if (TestLibrary.Utilities.IsNativeAot) { - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // https://github.com/dotnet/runtime/issues/83051 - // NativeAOT currently always returns empty string - Utils.Assert(processInfo2.ManagedEntrypointAssemblyName == string.Empty); + string expectedName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; + Utils.Assert(expectedName.Equals(processInfo2.ManagedEntrypointAssemblyName), + $"ManagedEntrypointAssemblyName must match. Expected: {expectedName}, Received: {processInfo2.ManagedEntrypointAssemblyName}"); } else { From e6d76cfe1a920ae8c469da0cbfe0e5d3dd0b21e4 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Thu, 15 Jun 2023 10:19:41 -0700 Subject: [PATCH 4/9] FB2 --- src/tests/Common/CoreCLRTestLibrary/Utilities.cs | 4 ++++ src/tests/tracing/Directory.Build.props | 8 ++++++++ src/tests/tracing/eventcounter/runtimecounters.csproj | 1 - .../tracing/eventpipe/config/name_config_with_pid.csproj | 1 - .../tracing/eventpipe/diagnosticport/diagnosticport.cs | 9 +-------- .../eventpipe/diagnosticport/diagnosticport.csproj | 1 - src/tests/tracing/eventpipe/processinfo/processinfo.cs | 2 +- .../tracing/eventpipe/processinfo/processinfo.csproj | 1 - src/tests/tracing/eventpipe/processinfo2/processinfo2.cs | 2 +- .../tracing/eventpipe/processinfo2/processinfo2.csproj | 1 - src/tests/tracing/eventpipe/reverse/reverse.csproj | 1 - .../simpleprovidervalidation.csproj | 1 - 12 files changed, 15 insertions(+), 17 deletions(-) create mode 100644 src/tests/tracing/Directory.Build.props diff --git a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs index a4f5c78796733e..c298a46abca874 100644 --- a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs +++ b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs @@ -95,6 +95,10 @@ public static bool IsWindowsIoTCore public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null; public static bool IsNotMonoRuntime => !IsMonoRuntime; public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported; + + public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location); + public static bool IsSingleFile => !HasAssemblyFiles; + #if NETCOREAPP public static bool IsReflectionEmitSupported => RuntimeFeature.IsDynamicCodeSupported; public static bool IsNotReflectionEmitSupported => !IsReflectionEmitSupported; diff --git a/src/tests/tracing/Directory.Build.props b/src/tests/tracing/Directory.Build.props new file mode 100644 index 00000000000000..4d3d8c7ee19c20 --- /dev/null +++ b/src/tests/tracing/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + true + + \ No newline at end of file diff --git a/src/tests/tracing/eventcounter/runtimecounters.csproj b/src/tests/tracing/eventcounter/runtimecounters.csproj index 5c364fac879eab..34660af281c07a 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.csproj +++ b/src/tests/tracing/eventcounter/runtimecounters.csproj @@ -7,7 +7,6 @@ true true - true diff --git a/src/tests/tracing/eventpipe/config/name_config_with_pid.csproj b/src/tests/tracing/eventpipe/config/name_config_with_pid.csproj index 187b43060edfb8..c090cb1e64fbf1 100644 --- a/src/tests/tracing/eventpipe/config/name_config_with_pid.csproj +++ b/src/tests/tracing/eventpipe/config/name_config_with_pid.csproj @@ -5,7 +5,6 @@ true true - true diff --git a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs index 7e2edfc3896fe4..68873c4aa95aa6 100644 --- a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs +++ b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs @@ -401,16 +401,9 @@ public static async Task TEST_CanGetProcessInfo2WhileSuspended() // Mono currently returns empty string if the runtime is suspended before an assembly is loaded Utils.Assert(string.IsNullOrEmpty(processInfo2.ManagedEntrypointAssemblyName)); } - else if (TestLibrary.Utilities.IsNativeAot) - { - string expectedName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; - Utils.Assert(expectedName.Equals(processInfo2.ManagedEntrypointAssemblyName), - $"ManagedEntrypointAssemblyName must match. Expected: {expectedName}, Received: {processInfo2.ManagedEntrypointAssemblyName}"); - } else { - // Assembly has not been loaded yet, so the assembly file name is used - string expectedName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location); + string expectedName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; Utils.Assert(expectedName.Equals(processInfo2.ManagedEntrypointAssemblyName), $"ManagedEntrypointAssemblyName must match. Expected: {expectedName}, Received: {processInfo2.ManagedEntrypointAssemblyName}"); } diff --git a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.csproj b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.csproj index 2dd6c137f33852..e266e498b4219d 100644 --- a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.csproj +++ b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.csproj @@ -7,7 +7,6 @@ true true - true diff --git a/src/tests/tracing/eventpipe/processinfo/processinfo.cs b/src/tests/tracing/eventpipe/processinfo/processinfo.cs index 5efe95aee8300b..4f0d6133cf1db4 100644 --- a/src/tests/tracing/eventpipe/processinfo/processinfo.cs +++ b/src/tests/tracing/eventpipe/processinfo/processinfo.cs @@ -149,7 +149,7 @@ public static int Main() // /path/to/corerun /path/to/processinfo.dll // or // "C:\path\to\CoreRun.exe" C:\path\to\processinfo.dll - string currentProcessCommandLine = TestLibrary.Utilities.IsNativeAot + string currentProcessCommandLine = TestLibrary.Utilities.IsSingleFile ? currentProcess.MainModule.FileName : $"{currentProcess.MainModule.FileName} {System.Reflection.Assembly.GetExecutingAssembly().Location}"; string receivedCommandLine = NormalizeCommandLine(commandLine); diff --git a/src/tests/tracing/eventpipe/processinfo/processinfo.csproj b/src/tests/tracing/eventpipe/processinfo/processinfo.csproj index 573d94f3a149ea..2c913f467d9e20 100644 --- a/src/tests/tracing/eventpipe/processinfo/processinfo.csproj +++ b/src/tests/tracing/eventpipe/processinfo/processinfo.csproj @@ -11,7 +11,6 @@ Issue: https://github.com/dotnet/runtime/issues/39935 --> true - true diff --git a/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs b/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs index 472392ecfb082a..589af8d1aa49f4 100644 --- a/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs +++ b/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs @@ -150,7 +150,7 @@ public static int Main() // /path/to/corerun /path/to/processinfo.dll // or // "C:\path\to\CoreRun.exe" C:\path\to\processinfo.dll - string currentProcessCommandLine = TestLibrary.Utilities.IsNativeAot + string currentProcessCommandLine = TestLibrary.Utilities.IsSingleFile ? currentProcess.MainModule.FileName : $"{currentProcess.MainModule.FileName} {System.Reflection.Assembly.GetExecutingAssembly().Location}"; string receivedCommandLine = NormalizeCommandLine(commandLine); diff --git a/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj b/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj index 573d94f3a149ea..2c913f467d9e20 100644 --- a/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj +++ b/src/tests/tracing/eventpipe/processinfo2/processinfo2.csproj @@ -11,7 +11,6 @@ Issue: https://github.com/dotnet/runtime/issues/39935 --> true - true diff --git a/src/tests/tracing/eventpipe/reverse/reverse.csproj b/src/tests/tracing/eventpipe/reverse/reverse.csproj index 4b4bae03bc0b50..a2fca0e2c1cca0 100644 --- a/src/tests/tracing/eventpipe/reverse/reverse.csproj +++ b/src/tests/tracing/eventpipe/reverse/reverse.csproj @@ -8,7 +8,6 @@ true true - true diff --git a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj b/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj index b9330517e010f5..18068018243a0b 100644 --- a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj +++ b/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj @@ -7,7 +7,6 @@ true true - true From 744856c877bf0cd3d7cdfdd70614856936bab5fe Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Thu, 6 Jul 2023 13:09:01 -0700 Subject: [PATCH 5/9] fix main merge issues --- eng/pipelines/runtime.yml | 93 ++++++------ .../simpleprovidervalidation.cs | 61 -------- .../simpleruntimeeventvalidation.cs | 133 ++++++++++++++++++ .../simpleruntimeeventvalidation.csproj} | 0 4 files changed, 175 insertions(+), 112 deletions(-) delete mode 100644 src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs create mode 100644 src/tests/tracing/eventpipe/simpleruntimeeventvalidation/simpleruntimeeventvalidation.cs rename src/tests/tracing/eventpipe/{simpleprovidervalidation/simpleprovidervalidation.csproj => simpleruntimeeventvalidation/simpleruntimeeventvalidation.csproj} (100%) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 13cc33d5346fe6..4d75c6feeec7a5 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -248,7 +248,7 @@ extends: extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml extraStepsParameters: creator: dotnet-bot - testBuildArgs: 'nativeaot tree ";nativeaot;Loader;Interop;tracing/eventpipe/config;tracing/eventpipe/diagnosticport;tracing/eventpipe/reverse;tracing/eventpipe/processinfo2;" test tracing/eventcounter/runtimecounters.csproj /p:BuildNativeAotFrameworkObjects=true' + testBuildArgs: 'nativeaot tree ";nativeaot;Loader;Interop;tracing/eventpipe/config;tracing/eventpipe/diagnosticport;tracing/eventpipe/reverse;tracing/eventpipe/processenvironment;tracing/eventpipe/simpleruntimeeventvalidation;tracing/eventpipe/processinfo2;" test tracing/eventcounter/runtimecounters.csproj /p:BuildNativeAotFrameworkObjects=true' liveLibrariesBuildConfig: Release testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig) extraVariablesTemplates: @@ -290,7 +290,7 @@ extends: extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml extraStepsParameters: creator: dotnet-bot - testBuildArgs: 'nativeaot tree ";nativeaot;tracing/eventpipe/simpleprovidervalidation;"' + testBuildArgs: 'nativeaot tree ";nativeaot;tracing/eventpipe/providervalidation;"' liveLibrariesBuildConfig: Release testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig) extraVariablesTemplates: @@ -505,14 +505,6 @@ extends: scenarios: - WasmTestOnBrowser - - template: /eng/pipelines/common/templates/wasm-build-only.yml - parameters: - platforms: - - browser_wasm - nameSuffix: _Threading_PerfTracing - extraBuildArgs: /p:MonoWasmBuildVariant=perftrace /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) - alwaysRun: ${{ variables.isRollingBuild }} - # WASI/WASM - template: /eng/pipelines/common/templates/wasm-library-tests.yml @@ -582,46 +574,43 @@ extends: # MacCatalyst interp - requires AOT Compilation and Interp flags # Build the whole product using Mono and run libraries tests # - # - # Disabled pending queue backup investigation - # - #- template: /eng/pipelines/common/platform-matrix.yml - # parameters: - # jobTemplate: /eng/pipelines/common/global-build-job.yml - # helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - # buildConfig: Release - # runtimeFlavor: mono - # platforms: - # - maccatalyst_x64 - # - ${{ if eq(variables['isRollingBuild'], true) }}: - # - maccatalyst_arm64 - # variables: - # # map dependencies variables to local variables - # - name: librariesContainsChange - # value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] - # - name: monoContainsChange - # value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono_excluding_wasm.containsChange'] ] - # jobParameters: - # testGroup: innerloop - # nameSuffix: AllSubsets_Mono - # buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true - # timeoutInMinutes: 180 - # condition: >- - # or( - # eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - # eq(dependencies.evaluate_paths.outputs['SetPathVars_mono_excluding_wasm.containsChange'], true), - # eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - # eq(variables['isRollingBuild'], true)) - # # extra steps, run tests - # extraStepsTemplate: /eng/pipelines/libraries/helix.yml - # extraStepsParameters: - # creator: dotnet-bot - # testRunNamePrefixSuffix: Mono_$(_BuildConfig) - # condition: >- - # or( - # eq(variables['librariesContainsChange'], true), - # eq(variables['monoContainsChange'], true), - # eq(variables['isRollingBuild'], true)) + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - maccatalyst_x64 + - ${{ if eq(variables['isRollingBuild'], true) }}: + - maccatalyst_arm64 + variables: + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono_excluding_wasm.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono_excluding_wasm.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isRollingBuild'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) # # Build Mono and Installer on LLVMJIT mode @@ -742,6 +731,7 @@ extends: buildConfig: release platforms: - linux_x64 + - linux_musl_x64 # - linux_arm64 # - linux_musl_arm64 - windows_x64 @@ -795,6 +785,7 @@ extends: buildConfig: release platforms: - linux_arm64 + - linux_musl_arm64 - osx_arm64 jobParameters: runtimeVariant: crossaot @@ -1236,7 +1227,7 @@ extends: testGroup: innerloop nameSuffix: AllSubsets_Mono_LLVMAot_RuntimeTests runtimeVariant: llvmaot - buildArgs: -s mono+libs+clr.hosts+clr.iltools -c Release /p:MonoEnableLLVM=true /p:MonoBundleLLVMOptimizer=true /p:MonoLLVMUseCxx11Abi=true + buildArgs: -s mono+libs+clr.hosts+clr.iltools -c Release /p:MonoEnableLLVM=true /p:MonoBundleLLVMOptimizer=true timeoutInMinutes: 180 condition: >- diff --git a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs b/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs deleted file mode 100644 index a954e0c3229899..00000000000000 --- a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics.Tracing; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Collections.Generic; -using Microsoft.Diagnostics.Tracing; -using Tracing.Tests.Common; -using Microsoft.Diagnostics.NETCore.Client; - -namespace Tracing.Tests.SimpleProviderValidation -{ - public sealed class MyEventSource : EventSource - { - private MyEventSource() {} - public static MyEventSource Log = new MyEventSource(); - public void MyEvent() { WriteEvent(1, "MyEvent"); } - } - - public class ProviderValidation - { - public static int Main() - { - // This test is meant to validate NativeAOT EventPipe implementation and is meant to run in regular CI - // Its currently not enabled in NativeAOT runs and the below issue tracks the work - // https://github.com/dotnet/runtime/issues/84701 - - var providers = new List() - { - new EventPipeProvider("MyEventSource", EventLevel.Verbose), - new EventPipeProvider("Microsoft-DotNETCore-SampleProfiler", EventLevel.Verbose) - }; - - var ret = IpcTraceTest.RunAndValidateEventCounts(_expectedEventCounts, _eventGeneratingAction, providers, 1024, enableRundownProvider:false); - if (ret < 0) - return ret; - else - return 100; - } - - private static Dictionary _expectedEventCounts = new Dictionary() - { - { "MyEventSource", 100_000 }, - { "Microsoft-DotNETCore-EventPipe", 1} - }; - - private static Action _eventGeneratingAction = () => - { - for (int i = 0; i < 100_000; i++) - { - if (i % 10_000 == 0) - Logger.logger.Log($"Fired MyEvent {i:N0}/100,000 times..."); - MyEventSource.Log.MyEvent(); - } - }; - } -} diff --git a/src/tests/tracing/eventpipe/simpleruntimeeventvalidation/simpleruntimeeventvalidation.cs b/src/tests/tracing/eventpipe/simpleruntimeeventvalidation/simpleruntimeeventvalidation.cs new file mode 100644 index 00000000000000..6a851e23385af8 --- /dev/null +++ b/src/tests/tracing/eventpipe/simpleruntimeeventvalidation/simpleruntimeeventvalidation.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics.Tracing; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Microsoft.Diagnostics.Tracing; +using Tracing.Tests.Common; +using Microsoft.Diagnostics.NETCore.Client; + +namespace Tracing.Tests.SimpleRuntimeEventValidation +{ + public class RuntimeEventValidation + { + public static int Main() + { + // This test validates GC and Exception events in the runtime + var ret = IpcTraceTest.RunAndValidateEventCounts( + // Validation is done with _DoesTraceContainEvents + new Dictionary(){{ "Microsoft-Windows-DotNETRuntime", -1 }}, + _eventGeneratingActionForGC, + //GCKeyword (0x1): 0b1 + new List(){new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, 0b1)}, + 1024, _DoesTraceContainGCEvents, enableRundownProvider:false); + + // Run the 2nd test scenario only if the first one passes + if(ret== 100) + { + ret = IpcTraceTest.RunAndValidateEventCounts( + new Dictionary(){{ "Microsoft-DotNETCore-EventPipe", 1 }}, + _eventGeneratingActionForExceptions, + //ExceptionKeyword (0x8000): 0b1000_0000_0000_0000 + new List(){new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Warning, 0b1000_0000_0000_0000)}, + 1024, _DoesTraceContainExceptionEvents, enableRundownProvider:false); + } + + if (ret < 0) + return ret; + else + return 100; + } + + private static Action _eventGeneratingActionForGC = () => + { + for (int i = 0; i < 50; i++) + { + if (i % 10 == 0) + Logger.logger.Log($"Called GC.Collect() {i} times..."); + RuntimeEventValidation eventValidation = new RuntimeEventValidation(); + eventValidation = null; + GC.Collect(); + } + }; + + private static Action _eventGeneratingActionForExceptions = () => + { + for (int i = 0; i < 10; i++) + { + if (i % 5 == 0) + Logger.logger.Log($"Thrown an exception {i} times..."); + try + { + throw new ArgumentNullException("Throw ArgumentNullException"); + } + catch (Exception e) + { + //Do nothing + } + } + }; + + private static Func> _DoesTraceContainGCEvents = (source) => + { + int GCStartEvents = 0; + int GCEndEvents = 0; + source.Clr.GCStart += (eventData) => GCStartEvents += 1; + source.Clr.GCStop += (eventData) => GCEndEvents += 1; + + int GCRestartEEStartEvents = 0; + int GCRestartEEStopEvents = 0; + source.Clr.GCRestartEEStart += (eventData) => GCRestartEEStartEvents += 1; + source.Clr.GCRestartEEStop += (eventData) => GCRestartEEStopEvents += 1; + + int GCSuspendEEEvents = 0; + int GCSuspendEEEndEvents = 0; + source.Clr.GCSuspendEEStart += (eventData) => GCSuspendEEEvents += 1; + source.Clr.GCSuspendEEStop += (eventData) => GCSuspendEEEndEvents += 1; + + return () => { + Logger.logger.Log("Event counts validation"); + + Logger.logger.Log("GCStartEvents: " + GCStartEvents); + Logger.logger.Log("GCEndEvents: " + GCEndEvents); + bool GCStartStopResult = GCStartEvents >= 50 && GCEndEvents >= 50 && Math.Abs(GCStartEvents - GCEndEvents) <=2; + Logger.logger.Log("GCStartStopResult check: " + GCStartStopResult); + + Logger.logger.Log("GCRestartEEStartEvents: " + GCRestartEEStartEvents); + Logger.logger.Log("GCRestartEEStopEvents: " + GCRestartEEStopEvents); + bool GCRestartEEStartStopResult = GCRestartEEStartEvents >= 50 && GCRestartEEStopEvents >= 50; + Logger.logger.Log("GCRestartEEStartStopResult check: " + GCRestartEEStartStopResult); + + Logger.logger.Log("GCSuspendEEEvents: " + GCSuspendEEEvents); + Logger.logger.Log("GCSuspendEEEndEvents: " + GCSuspendEEEndEvents); + bool GCSuspendEEStartStopResult = GCSuspendEEEvents >= 50 && GCSuspendEEEndEvents >= 50; + Logger.logger.Log("GCSuspendEEStartStopResult check: " + GCSuspendEEStartStopResult); + + return GCStartStopResult && GCRestartEEStartStopResult && GCSuspendEEStartStopResult ? 100 : -1; + }; + }; + + private static Func> _DoesTraceContainExceptionEvents = (source) => + { + int ExStartEvents = 0; + source.Clr.ExceptionStart += (eventData) => + { + if(eventData.ToString().IndexOf("System.ArgumentNullException")>=0) + ExStartEvents += 1; + }; + + return () => { + Logger.logger.Log("Exception Event counts validation"); + Logger.logger.Log("ExStartEvents: " + ExStartEvents); + bool ExStartResult = ExStartEvents >= 10; + + return ExStartResult ? 100 : -1; + }; + }; + } +} diff --git a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj b/src/tests/tracing/eventpipe/simpleruntimeeventvalidation/simpleruntimeeventvalidation.csproj similarity index 100% rename from src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj rename to src/tests/tracing/eventpipe/simpleruntimeeventvalidation/simpleruntimeeventvalidation.csproj From 98129b3fa16238c1a6c9b30c8436222c6566cf07 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Fri, 7 Jul 2023 09:50:52 -0700 Subject: [PATCH 6/9] Using assembly location for coreclr per FB --- .../tracing/eventpipe/diagnosticport/diagnosticport.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs index 68873c4aa95aa6..1c080255beac98 100644 --- a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs +++ b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs @@ -401,12 +401,18 @@ public static async Task TEST_CanGetProcessInfo2WhileSuspended() // Mono currently returns empty string if the runtime is suspended before an assembly is loaded Utils.Assert(string.IsNullOrEmpty(processInfo2.ManagedEntrypointAssemblyName)); } - else + else if (TestLibrary.Utilities.IsNativeAot) { string expectedName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; Utils.Assert(expectedName.Equals(processInfo2.ManagedEntrypointAssemblyName), $"ManagedEntrypointAssemblyName must match. Expected: {expectedName}, Received: {processInfo2.ManagedEntrypointAssemblyName}"); } + else + { + string expectedName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location); + Utils.Assert(expectedName.Equals(processInfo2.ManagedEntrypointAssemblyName), + $"ManagedEntrypointAssemblyName must match. Expected: {expectedName}, Received: {processInfo2.ManagedEntrypointAssemblyName}"); + } // send resume command on this connection var message = new IpcMessage(0x04,0x01); From 001245152cebe3f67c1b8afcc24558f459d6ec71 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Tue, 11 Jul 2023 12:37:17 -0700 Subject: [PATCH 7/9] FB --- .../nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index 27ed1b1c0bd09b..0b2f6655ca4ea5 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -95,49 +95,53 @@ ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) // Cannot use __cpp_threadsafe_static_init feature since it will bring in the C++ runtime and need to use threadsafe way to initialize entrypoint_assembly_name static const ep_char8_t * entrypoint_assembly_name = nullptr; if (entrypoint_assembly_name == nullptr) { - const ep_char8_t * entrypoint_assembly_name_local; + ep_char8_t * entrypoint_assembly_name_local; #ifdef HOST_WINDOWS const TCHAR * wszModuleFileName = NULL; - if(PalGetModuleFileName(&wszModuleFileName, nullptr) == 0) - entrypoint_assembly_name_local = reinterpret_cast(""); - else { + if(PalGetModuleFileName(&wszModuleFileName, nullptr) == 0) { + // Allocating since we delete this empty string later + entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); + entrypoint_assembly_name_local = reinterpret_cast('\0'); + } else { const wchar_t* process_name = wcsrchr(wszModuleFileName, '\\'); if (process_name != NULL) { - const wchar_t* extension = wcschr(process_name + 1, '.'); + // We don't want to include the first '\' + process_name++; + const wchar_t* extension = wcschr(process_name, '.'); if (extension != NULL) { - // We don't want to include the first '\' - size_t len = extension - (process_name + 1); - wchar_t* process_name_wo_ext = reinterpret_cast(malloc(len + 1)); - wcsncpy(process_name_wo_ext, process_name + 1, len); - process_name_wo_ext[len] = L'\0'; - const ep_char16_t* process_name_wo_ext_l = reinterpret_cast(process_name_wo_ext); - entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_wo_ext_l, -1); + size_t len = extension - process_name; + const ep_char16_t* process_name_wo_ext_l = reinterpret_cast(process_name); + entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_wo_ext_l, len); } else { - const ep_char16_t* process_name_l = reinterpret_cast(process_name + 1); + const ep_char16_t* process_name_l = reinterpret_cast(process_name); entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_l, -1); } + } else{ + // Allocating since we delete this empty string later + entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); + entrypoint_assembly_name_local = reinterpret_cast('\0'); } - else - entrypoint_assembly_name_local = reinterpret_cast(""); } -#else -#if defined (__linux__) +#elif defined (__linux__) size_t program_len = strlen(__progname); ep_char8_t *process_name = reinterpret_cast(malloc(program_len + 1)); - if (process_name == NULL) - entrypoint_assembly_name_local = reinterpret_cast(""); - else { - memcpy (process_name, __progname, program_len); - process_name[program_len] = '\0'; + if (process_name == NULL) { + // Allocating since we delete this empty string later + entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); + entrypoint_assembly_name_local = reinterpret_cast('\0'); + } else { char *dot = strrchr(process_name, '.'); if (dot != NULL) { - *dot = '\0'; + program_len = program_len - strlen(dot); + } + memcpy (process_name, __progname, program_len); + process_name[program_len] = '\0'; } - entrypoint_assembly_name_local = reinterpret_cast(process_name); - } + entrypoint_assembly_name_local = reinterpret_cast(process_name); #else - entrypoint_assembly_name_local = reinterpret_cast(""); -#endif // __linux__ + // Allocating since we delete this empty string later + entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); + entrypoint_assembly_name_local = reinterpret_cast('\0'); #endif // HOST_WINDOWS if (PalInterlockedCompareExchangePointer((void**)(&entrypoint_assembly_name), (void*)(entrypoint_assembly_name_local), nullptr) != nullptr) From e909d164277fa9d77b419588f8e5e844d06ad1f5 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Wed, 12 Jul 2023 10:11:54 -0700 Subject: [PATCH 8/9] FB --- .../nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | 90 +++++++++---------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index 0b2f6655ca4ea5..e88f1bcb0c5917 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -28,6 +28,14 @@ #include "holder.h" #include "SpinLock.h" +#ifndef DIRECTORY_SEPARATOR_CHAR +#ifdef TARGET_UNIX +#define DIRECTORY_SEPARATOR_CHAR '/' +#else // TARGET_UNIX +#define DIRECTORY_SEPARATOR_CHAR '\\' +#endif // TARGET_UNIX +#endif + #ifdef TARGET_UNIX // Per module (1 for NativeAOT), key that will be used to implement TLS in Unix pthread_key_t eventpipe_tls_key; @@ -84,69 +92,59 @@ ep_rt_aot_sample_profiler_write_sampling_event_for_threads ( { } -#if defined (__linux__) -extern char *__progname; -#endif - const ep_char8_t * ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) { - // Although PalGetModuleFileName exists, non-windows implementation has issues and we use __progname for Linux. // Cannot use __cpp_threadsafe_static_init feature since it will bring in the C++ runtime and need to use threadsafe way to initialize entrypoint_assembly_name static const ep_char8_t * entrypoint_assembly_name = nullptr; if (entrypoint_assembly_name == nullptr) { ep_char8_t * entrypoint_assembly_name_local; -#ifdef HOST_WINDOWS const TCHAR * wszModuleFileName = NULL; - if(PalGetModuleFileName(&wszModuleFileName, nullptr) == 0) { - // Allocating since we delete this empty string later + HANDLE moduleHandle = PalGetModuleHandleFromPointer((void*)&ep_rt_aot_entrypoint_assembly_name_get_utf8); + if(PalGetModuleFileName(&wszModuleFileName, moduleHandle) == 0) { entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); - entrypoint_assembly_name_local = reinterpret_cast('\0'); - } else { - const wchar_t* process_name = wcsrchr(wszModuleFileName, '\\'); - if (process_name != NULL) { - // We don't want to include the first '\' - process_name++; - const wchar_t* extension = wcschr(process_name, '.'); - if (extension != NULL) { - size_t len = extension - process_name; - const ep_char16_t* process_name_wo_ext_l = reinterpret_cast(process_name); - entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_wo_ext_l, len); - } else { - const ep_char16_t* process_name_l = reinterpret_cast(process_name); - entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name_l, -1); - } - } else{ - // Allocating since we delete this empty string later - entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); - entrypoint_assembly_name_local = reinterpret_cast('\0'); + if(entrypoint_assembly_name_local==NULL) { + return NULL; } + *entrypoint_assembly_name_local = '\0'; } -#elif defined (__linux__) - size_t program_len = strlen(__progname); - ep_char8_t *process_name = reinterpret_cast(malloc(program_len + 1)); - if (process_name == NULL) { - // Allocating since we delete this empty string later - entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); - entrypoint_assembly_name_local = reinterpret_cast('\0'); - } else { - char *dot = strrchr(process_name, '.'); - if (dot != NULL) { - program_len = program_len - strlen(dot); + else { +#ifdef HOST_WINDOWS + const wchar_t* process_name_const = wcsrchr(wszModuleFileName, DIRECTORY_SEPARATOR_CHAR); + if (process_name_const != NULL) { + process_name_const++; } - memcpy (process_name, __progname, program_len); - process_name[program_len] = '\0'; - } - entrypoint_assembly_name_local = reinterpret_cast(process_name); + size_t len = -1; + const wchar_t* extension = wcsrchr(process_name_const, '.'); + if (extension != NULL) { + len = extension - process_name_const; + } + const ep_char16_t* process_name = reinterpret_cast(process_name_const); + entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name, len); #else - // Allocating since we delete this empty string later - entrypoint_assembly_name_local = reinterpret_cast(malloc(1)); - entrypoint_assembly_name_local = reinterpret_cast('\0'); + const ep_char8_t* process_name_const = strrchr(wszModuleFileName, DIRECTORY_SEPARATOR_CHAR); + if (process_name_const != NULL) { + process_name_const++; + } + size_t len = strlen(process_name_const); + const ep_char8_t *extension = strrchr(process_name_const, '.'); + if (extension != NULL) { + len = len - strlen(extension); + } + ep_char8_t* process_name = reinterpret_cast(malloc(len + 1)); + if (process_name == NULL) { + return NULL; + } + memcpy(process_name, process_name_const, len); + process_name[len] = '\0'; + entrypoint_assembly_name_local = reinterpret_cast(process_name); #endif // HOST_WINDOWS + } if (PalInterlockedCompareExchangePointer((void**)(&entrypoint_assembly_name), (void*)(entrypoint_assembly_name_local), nullptr) != nullptr) - delete[] entrypoint_assembly_name_local; + free(entrypoint_assembly_name_local); } + return reinterpret_cast(entrypoint_assembly_name); } From 304d2cf5096418a15a344abd54a51362e3e0c047 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Fri, 14 Jul 2023 05:47:13 -0700 Subject: [PATCH 9/9] FB --- .../nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | 14 ++++++++++---- .../eventpipe/diagnosticport/diagnosticport.cs | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index e88f1bcb0c5917..944d7714880b95 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -95,6 +95,7 @@ ep_rt_aot_sample_profiler_write_sampling_event_for_threads ( const ep_char8_t * ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) { + // We are (intentionally for now) using the module name rather than entry assembly // Cannot use __cpp_threadsafe_static_init feature since it will bring in the C++ runtime and need to use threadsafe way to initialize entrypoint_assembly_name static const ep_char8_t * entrypoint_assembly_name = nullptr; if (entrypoint_assembly_name == nullptr) { @@ -114,22 +115,27 @@ ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) if (process_name_const != NULL) { process_name_const++; } + else { + process_name_const = reinterpret_cast(wszModuleFileName); + } size_t len = -1; const wchar_t* extension = wcsrchr(process_name_const, '.'); if (extension != NULL) { len = extension - process_name_const; } - const ep_char16_t* process_name = reinterpret_cast(process_name_const); - entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(process_name, len); + entrypoint_assembly_name_local = ep_rt_utf16_to_utf8_string(reinterpret_cast(process_name_const), len); #else const ep_char8_t* process_name_const = strrchr(wszModuleFileName, DIRECTORY_SEPARATOR_CHAR); if (process_name_const != NULL) { process_name_const++; } + else { + process_name_const = reinterpret_cast(wszModuleFileName); + } size_t len = strlen(process_name_const); const ep_char8_t *extension = strrchr(process_name_const, '.'); if (extension != NULL) { - len = len - strlen(extension); + len = extension - process_name_const; } ep_char8_t* process_name = reinterpret_cast(malloc(len + 1)); if (process_name == NULL) { @@ -145,7 +151,7 @@ ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) free(entrypoint_assembly_name_local); } - return reinterpret_cast(entrypoint_assembly_name); + return entrypoint_assembly_name; } const ep_char8_t * diff --git a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs index 1c080255beac98..7e2edfc3896fe4 100644 --- a/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs +++ b/src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs @@ -409,6 +409,7 @@ public static async Task TEST_CanGetProcessInfo2WhileSuspended() } else { + // Assembly has not been loaded yet, so the assembly file name is used string expectedName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location); Utils.Assert(expectedName.Equals(processInfo2.ManagedEntrypointAssemblyName), $"ManagedEntrypointAssemblyName must match. Expected: {expectedName}, Received: {processInfo2.ManagedEntrypointAssemblyName}");