[profiler] Load the profiler with MONO_DL_EAGER.
authorAlex Rønne Petersen <alexrp@xamarin.com>
Wed, 13 Apr 2016 18:19:12 +0000 (20:19 +0200)
committerRodrigo Kumpera <kumpera@gmail.com>
Tue, 19 Apr 2016 21:34:46 +0000 (14:34 -0700)
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
mono/profiler/proflog.c

index dcf0cebcc83f94737db5acf94a59ad938158f3d9..4920694b731f928265424c78bfa730b5238bd7aa 100644 (file)
@@ -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)
index ed92589a887445a5cb19448eb21111c8f9945795..3f215535b80f6df7689e96ef2405f75b3eb2eb2d 100644 (file)
@@ -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;