Skip to content

Commit

Permalink
Initial work porting native diagnostic server library to C library po…
Browse files Browse the repository at this point in the history
…tentially shared between runtimes.

PR handling port of Diagnostic Server C++ library from CoreCLR into a C library that can be shared between Mono as well as CoreCLR runtime. Port follows same guidelines setup for event pipe port dotnet/runtime#34600. Diagnostic server library is currently hosted as part of event pipe library but hosting its own runtime shim as well as source files (so could be split into separate library if ever make sense). Diagnostic Server have dependencies on event pipe library (and reuse part of event pipe runtime shim from its own shim).

This is the first PR getting the code from diagnostic server codebase over to C library. Once that is done there will be follow up PR's starting to enabling more of the CoreCLR tests suites over event pipe currently depending on diagnostic server and connection between diagnostic server and event pipe library.

Diagnostic server processinfo, https://github.com/dotnet/runtime/tree/master/src/tests/tracing/eventpipe/processinfo, test pass running on Windows/Linux Mono.

eventpipe buffersize, https://github.com/dotnet/runtime/tree/master/src/tests/tracing/eventpipe/buffersize, test pass running on Windows/Linux Mono, connecting diagnostic server with eventpipe and IPC test clients and parsers.

TODO's before this PR can be merged:

- [x] Fix all builds (currently only validated on Windows).
- [x] Port POSIX PAL.
- [x] Get pass on process info on Linux/Mac enabling the test as part of PR.
- [x] Implement WriteEvent icall as well as starting IPC streaming thread in event pipe library.
- [x] Get pass on one test consuming event pipe data over IPC.
  • Loading branch information
lateralusX committed Oct 2, 2020
1 parent 15c25d7 commit a628496
Show file tree
Hide file tree
Showing 15 changed files with 343 additions and 20 deletions.
1 change: 1 addition & 0 deletions mono/metadata/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ common_sources = \
domain-internals.h \
environment.c \
environment.h \
environment-internals.h \
icall-eventpipe.c \
exception.c \
exception.h \
Expand Down
10 changes: 10 additions & 0 deletions mono/metadata/appdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@
#include <mono/metadata/w32handle.h>
#include <mono/metadata/w32error.h>
#include <mono/utils/w32api.h>

#ifdef ENABLE_PERFTRACING
#include <mono/eventpipe/ds-server.h>
#endif

#ifdef HOST_WIN32
#include <direct.h>
#endif
Expand Down Expand Up @@ -346,6 +351,11 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT

mono_thread_attach (domain);

#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
ds_server_init ();
ds_server_pause_for_diagnostics_monitor ();
#endif

mono_type_initialization_init ();

if (!mono_runtime_get_no_exec ())
Expand Down
16 changes: 16 additions & 0 deletions mono/metadata/environment-internals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* \file
*
* Copyright 2020 Microsoft
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#ifndef _MONO_METADATA_ENVIRONMENT_INTERNALS_H_
#define _MONO_METADATA_ENVIRONMENT_INTERNALS_H_

void
mono_set_os_args (int argc, char **argv);

char *
mono_get_os_cmd_line (void);

#endif /* _MONO_METADATA_ENVIRONMENT_INTERNALS_H_ */
17 changes: 17 additions & 0 deletions mono/metadata/environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <mono/metadata/appdomain.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/environment-internals.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/handle.h>
#include <mono/utils/mono-compiler.h>
Expand Down Expand Up @@ -45,6 +46,22 @@ mono_environment_exitcode_set (gint32 value)
exitcode=value;
}

static int mini_argc = 0;
static char **mini_argv = NULL;

void
mono_set_os_args (int argc, char **argv)
{
mini_argc = argc;
mini_argv = argv;
}

char *
mono_get_os_cmd_line (void)
{
return mono_runtime_get_cmd_line (mini_argc, mini_argv);
}

#ifndef ENABLE_NETCORE
/* note: we better manipulate the string in managed code (easier and safer) */
MonoStringHandle
Expand Down
2 changes: 1 addition & 1 deletion mono/metadata/icall-decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ ICALL_EXPORT MonoBoolean ves_icall_System_Diagnostics_Tracing_EventPipeInternal_
ICALL_EXPORT intptr_t ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetProvider (const_gunichar2_ptr provider_name);
ICALL_EXPORT MonoBoolean ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetSessionInfo (uint64_t session_id, void *session_info);
ICALL_EXPORT intptr_t ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t session_id);
ICALL_EXPORT void ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (intptr_t event_handle, const void *event_data, uint32_t data_count, const uint8_t *activity_id, const uint8_t *related_activity_id);
ICALL_EXPORT void ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (intptr_t event_handle, void *event_data, uint32_t event_data_len, const uint8_t *activity_id, const uint8_t *related_activity_id);
#endif

ICALL_EXPORT void ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array);
Expand Down
57 changes: 40 additions & 17 deletions mono/metadata/icall-eventpipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ typedef struct _EventPipeProviderConfigurationNative {
gunichar2 *filter_data;
} EventPipeProviderConfigurationNative;

typedef struct _EventProviderEventData {
uint64_t ptr;
uint32_t size;
uint32_t reserved;
} EventProviderEventData;

typedef struct _EventPipeSessionInfo {
int64_t starttime_as_utc_filetime;
int64_t start_timestamp;
Expand All @@ -64,9 +58,6 @@ gpointer ep_rt_mono_rand_provider;
static ep_rt_thread_holder_alloc_func thread_holder_alloc_callback_func;
static ep_rt_thread_holder_free_func thread_holder_free_callback_func;

void
mono_eventpipe_raise_thread_exited (uint64_t);

static
gboolean
rand_try_get_bytes_func (guchar *buffer, gssize buffer_size, MonoError *error)
Expand Down Expand Up @@ -114,15 +105,40 @@ profiler_eventpipe_thread_exited (MonoProfiler *prof, uintptr_t tid)
eventpipe_thread_exited ();
}

static
gpointer
eventpipe_thread_attach (gboolean background_thread)
{
MonoThread *thread = NULL;

// NOTE, under netcore, only root domain exists.
if (!mono_thread_current ()) {
thread = mono_thread_attach (mono_get_root_domain ());
if (background_thread) {
mono_thread_set_state (thread, ThreadState_Background);
mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
}
}

return thread;
}

static
void
eventpipe_thread_detach (void)
{
MonoThread *current_thread = mono_thread_current ();
if (current_thread)
mono_thread_detach (current_thread);
}

void
mono_eventpipe_init (
EventPipeMonoFuncTable *table,
ep_rt_thread_holder_alloc_func thread_holder_alloc_func,
ep_rt_thread_holder_free_func thread_holder_free_func)
{
if (table != NULL) {
table->ep_rt_mono_100ns_datetime = mono_100ns_datetime;
table->ep_rt_mono_100ns_ticks = mono_100ns_ticks;
table->ep_rt_mono_cpu_count = mono_cpu_count;
table->ep_rt_mono_process_current_pid = mono_process_current_pid;
table->ep_rt_mono_native_thread_id_get = mono_native_thread_id_get;
Expand All @@ -144,6 +160,11 @@ mono_eventpipe_init (
table->ep_rt_mono_valloc = mono_valloc;
table->ep_rt_mono_vfree = mono_vfree;
table->ep_rt_mono_valloc_granule = mono_valloc_granule;
table->ep_rt_mono_thread_platform_create_thread = mono_thread_platform_create_thread;
table->ep_rt_mono_thread_attach = eventpipe_thread_attach;
table->ep_rt_mono_thread_detach = eventpipe_thread_detach;
table->ep_rt_mono_get_os_cmd_line = mono_get_os_cmd_line;
table->ep_rt_mono_get_managed_cmd_line = mono_runtime_get_managed_cmd_line;
}

thread_holder_alloc_callback_func = thread_holder_alloc_func;
Expand Down Expand Up @@ -447,12 +468,14 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t s
void
ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (
intptr_t event_handle,
/* EventProviderEventData[] */const void *event_data,
uint32_t data_len,
/* EventData[] */void *event_data,
uint32_t event_data_len,
/* GUID * */const uint8_t *activity_id,
/* GUID * */const uint8_t *related_activity_id)
{
;
g_assert (event_handle);
EventPipeEvent *ep_event = (EventPipeEvent *)event_handle;
ep_write_event (ep_event, (EventData *)event_data, event_data_len, activity_id, related_activity_id);
}

#else /* ENABLE_PERFTRACING */
Expand Down Expand Up @@ -567,8 +590,8 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t s
void
ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (
intptr_t event_handle,
/* EventProviderEventData[] */const void *event_data,
uint32_t data_len,
/* EventData[] */void *event_data,
uint32_t event_data_len,
/* GUID * */const uint8_t *activity_id,
/* GUID * */const uint8_t *related_activity_id)
{
Expand All @@ -580,4 +603,4 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (
#endif /* ENABLE_PERFTRACING */
#endif /* ENABLE_NETCORE */

MONO_EMPTY_SOURCE_FILE (eventpipe_rt_mono);
MONO_EMPTY_SOURCE_FILE (icall_eventpipe);
6 changes: 6 additions & 0 deletions mono/metadata/object-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -2421,4 +2421,10 @@ mono_gc_wbarrier_value_copy_internal (void* dest, const void* src, int count, Mo
void
mono_gc_wbarrier_object_copy_internal (MonoObject* obj, MonoObject *src);

char *
mono_runtime_get_managed_cmd_line (void);

char *
mono_runtime_get_cmd_line (int argc, char **argv);

#endif /* __MONO_OBJECT_INTERNALS_H__ */
121 changes: 121 additions & 0 deletions mono/metadata/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ static GENERATE_GET_CLASS_WITH_CACHE (asyncresult, "System.Runtime.Remoting.Mess
#define ldstr_unlock() mono_coop_mutex_unlock (&ldstr_section)
static MonoCoopMutex ldstr_section;

static GString *
quote_escape_and_append_string (char *src_str, GString *target_str);

static GString *
format_cmd_line (int argc, char **argv, gboolean add_host);

/**
* mono_runtime_object_init:
Expand Down Expand Up @@ -4536,6 +4541,7 @@ free_main_args (void)
for (i = 0; i < num_main_args; ++i)
g_free (main_args [i]);
g_free (main_args);

num_main_args = 0;
main_args = NULL;
}
Expand Down Expand Up @@ -9467,6 +9473,121 @@ mono_vtype_get_field_addr (gpointer vtype, MonoClassField *field)
return ((char*)vtype) + field->offset - MONO_ABI_SIZEOF (MonoObject);
}

static GString *
quote_escape_and_append_string (char *src_str, GString *target_str)
{
#ifdef HOST_WIN32
char quote_char = '\"';
char escape_chars[] = "\"\\";
#else
char quote_char = '\'';
char escape_chars[] = "\'\\";
#endif

gboolean need_quote = FALSE;
gboolean need_escape = FALSE;

for (char *pos = src_str; *pos; ++pos) {
if (isspace (*pos))
need_quote = TRUE;
if (strchr (escape_chars, *pos))
need_escape = TRUE;
}

if (need_quote)
target_str = g_string_append_c (target_str, quote_char);

if (need_escape) {
for (char *pos = src_str; *pos; ++pos) {
if (strchr (escape_chars, *pos))
target_str = g_string_append_c (target_str, '\\');
target_str = g_string_append_c (target_str, *pos);
}
} else {
target_str = g_string_append (target_str, src_str);
}

if (need_quote)
target_str = g_string_append_c (target_str, quote_char);

return target_str;
}

static GString *
format_cmd_line (int argc, char **argv, gboolean add_host)
{
size_t total_size = 0;
char *host_path = NULL;
GString *cmd_line = NULL;

if (add_host) {
#if !defined(HOST_WIN32) && defined(HAVE_UNISTD_H)
host_path = mono_w32process_get_path (getpid ());
#elif defined(HOST_WIN32)
gunichar2 *host_path_ucs2 = NULL;
guint32 host_path_ucs2_len = 0;
if (mono_get_module_filename (NULL, &host_path_ucs2, &host_path_ucs2_len)) {
host_path = g_utf16_to_utf8 (host_path_ucs2, -1, NULL, NULL, NULL);
g_free (host_path_ucs2);
}
#endif
}

if (host_path)
// quote + string + quote
total_size += strlen (host_path) + 2;

for (int i = 0; i < argc; ++i) {
if (argv [i]) {
if (total_size > 0) {
// add space
total_size++;
}
// quote + string + quote
total_size += strlen (argv [i]) + 2;
}
}

// String will grow if needed, so not over allocating
// to handle case of escaped characters in arguments, if
// that happens string will automatically grow.
cmd_line = g_string_sized_new (total_size + 1);

if (cmd_line) {
if (host_path)
cmd_line = quote_escape_and_append_string (host_path, cmd_line);

for (int i = 0; i < argc; ++i) {
if (argv [i]) {
if (cmd_line->len > 0) {
// add space
cmd_line = g_string_append_c (cmd_line, ' ');
}
cmd_line = quote_escape_and_append_string (argv [i], cmd_line);
}
}
}

g_free (host_path);

return cmd_line;
}

char *
mono_runtime_get_cmd_line (int argc, char **argv)
{
MONO_REQ_GC_NEUTRAL_MODE;
GString *cmd_line = format_cmd_line (num_main_args, main_args, FALSE);
return cmd_line ? g_string_free (cmd_line, FALSE) : NULL;
}

char *
mono_runtime_get_managed_cmd_line (void)
{
MONO_REQ_GC_NEUTRAL_MODE;
GString *cmd_line = format_cmd_line (num_main_args, main_args, TRUE);
return cmd_line ? g_string_free (cmd_line, FALSE) : NULL;
}

#if NEVER_DEFINED
/*
Expand Down
3 changes: 3 additions & 0 deletions mono/mini/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/environment-internals.h>
#include <mono/metadata/verify.h>
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/mono-debug.h>
Expand Down Expand Up @@ -2644,6 +2645,8 @@ mono_main (int argc, char* argv[])
}

mono_set_defaults (mini_verbose_level, opt);
mono_set_os_args (argc, argv);

domain = mini_init (argv [i], forced_version);

mono_gc_set_stack_end (&domain);
Expand Down
Loading

0 comments on commit a628496

Please sign in to comment.