[profiler] Properly clean up the resources used by the profiler API on shutdown.
authorAlex Rønne Petersen <alexrp@xamarin.com>
Sat, 5 Aug 2017 16:49:56 +0000 (18:49 +0200)
committerAlex Rønne Petersen <alpeters@microsoft.com>
Mon, 7 Aug 2017 20:38:26 +0000 (22:38 +0200)
Also introduce mono_profiler_set_cleanup_callback ().

mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/profiler.h

index 340a70d3059c5f03c2d6250bb1deb620f9518329..976f309ee8717dccc6f3c5f19b502244efc8d24e 100644 (file)
@@ -16,6 +16,7 @@
 struct _MonoProfilerDesc {
        MonoProfilerHandle next;
        MonoProfiler *prof;
+       volatile gpointer cleanup_callback;
        volatile gpointer coverage_filter;
        volatile gpointer call_instrumentation_filter;
 
index 0f429f607ff9a6c2b3823f3fd43208103455ffa2..23f65469c81d412832909bd5b1f3d080072a1d74 100644 (file)
@@ -157,6 +157,12 @@ mono_profiler_create (MonoProfiler *prof)
        return handle;
 }
 
+void
+mono_profiler_set_cleanup_callback (MonoProfilerHandle handle, MonoProfilerCleanupCallback cb)
+{
+       InterlockedWritePointer (&handle->cleanup_callback, (gpointer) cb);
+}
+
 void
 mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb)
 {
@@ -478,6 +484,38 @@ mono_profiler_cleanup (void)
 #undef MONO_PROFILER_EVENT_3
 #undef MONO_PROFILER_EVENT_4
 #undef _MONO_PROFILER_EVENT
+
+       MonoProfilerHandle head = mono_profiler_state.profilers;
+
+       while (head) {
+               MonoProfilerCleanupCallback cb = head->cleanup_callback;
+
+               if (cb)
+                       cb (head->prof);
+
+               MonoProfilerHandle cur = head;
+               head = head->next;
+
+               g_free (cur);
+       }
+
+       if (mono_profiler_state.code_coverage) {
+               mono_os_mutex_destroy (&mono_profiler_state.coverage_mutex);
+
+               GHashTableIter iter;
+
+               g_hash_table_iter_init (&iter, mono_profiler_state.coverage_hash);
+
+               MonoProfilerCoverageInfo *info;
+
+               while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
+                       g_free (info);
+
+               g_hash_table_destroy (mono_profiler_state.coverage_hash);
+       }
+
+       if (mono_profiler_state.sampling_owner)
+               mono_os_sem_destroy (&mono_profiler_state.sampling_semaphore);
 }
 
 static void
index 76759d9f845d22acc3e9f14893332e73b74437c4..e20dc34c85472d8929d6a512356351e519e680a3 100644 (file)
@@ -63,6 +63,18 @@ typedef struct _MonoProfilerDesc *MonoProfilerHandle;
  */
 MONO_API MonoProfilerHandle mono_profiler_create (MonoProfiler *prof);
 
+typedef void (*MonoProfilerCleanupCallback) (MonoProfiler *prof);
+
+/*
+ * Sets a profiler cleanup function. This function will be invoked at shutdown
+ * when the profiler API is cleaning up its internal structures. It's mainly
+ * intended for a profiler to free the structure pointer that was passed to
+ * mono_profiler_create, if necessary.
+ *
+ * This function is async safe.
+ */
+MONO_API void mono_profiler_set_cleanup_callback (MonoProfilerHandle handle, MonoProfilerCleanupCallback cb);
+
 /*
  * Enables support for code coverage instrumentation. At the moment, this means
  * enabling the debug info subsystem. If you do not call this function, you