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