From e91ee2b0fd297dbb5ed9f6080552cf7183286890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 13 Apr 2016 20:19:12 +0200 Subject: [PATCH] [profiler] Load the profiler with MONO_DL_EAGER. We need to make sure all external references have been resolved so that we don't invoke the dynamic linker in the mono_sample_hit () callback which is called in async-signal context. --- mono/metadata/profiler.c | 14 +++++++++++--- mono/profiler/proflog.c | 8 ++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index dcf0cebcc83f9..4920694b731f9 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -1147,7 +1147,15 @@ load_embedded_profiler (const char *desc, const char *name) MonoDl *pmodule = NULL; gboolean result; - pmodule = mono_dl_open (NULL, MONO_DL_LAZY, &err); + /* + * Some profilers (such as ours) may need to call back into the runtime + * from their sampling callback (which is called in async-signal context). + * They need to be able to know that all references back to the runtime + * have been resolved; otherwise, calling runtime functions may result in + * invoking the dynamic linker which is not async-signal-safe. Passing + * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront. + */ + pmodule = mono_dl_open (NULL, MONO_DL_EAGER, &err); if (!pmodule) { g_warning ("Could not open main executable (%s)", err); g_free (err); @@ -1175,7 +1183,7 @@ load_profiler_from_directory (const char *directory, const char *libname, const iter = NULL; err = NULL; while ((path = mono_dl_build_path (directory, libname, &iter))) { - pmodule = mono_dl_open (path, MONO_DL_LAZY, &err); + pmodule = mono_dl_open (path, MONO_DL_EAGER, &err); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler: %s, %ssuccessful, err: %s", path, pmodule?"":"not ", err); g_free (path); g_free (err); @@ -1190,7 +1198,7 @@ static gboolean load_profiler_from_mono_installation (const char *libname, const char *desc) { char *err = NULL; - MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_LAZY, &err); + MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler from runtime libs: %s, %ssuccessful, err: %s", libname, pmodule?"":"not ", err); g_free (err); if (pmodule) diff --git a/mono/profiler/proflog.c b/mono/profiler/proflog.c index ed92589a88744..3f215535b80f6 100644 --- a/mono/profiler/proflog.c +++ b/mono/profiler/proflog.c @@ -2063,6 +2063,14 @@ enqueue_sample_hit (gpointer p) static void mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context) { + /* + * Please note: We rely on the runtime loading the profiler with + * MONO_DL_EAGER (RTLD_NOW) so that references to runtime functions within + * this function (and its siblings) are resolved when the profiler is + * loaded. Otherwise, we would potentially invoke the dynamic linker when + * invoking runtime functions, which is not async-signal-safe. + */ + if (in_shutdown) return;