Merge pull request #2720 from mono/fix-39325
[mono.git] / mono / profiler / proflog.c
index 7d4a3acc3ae08ed2a6e0a73222119527dce9c25c..188a40a26479643bb1e32c3b4ca84e439d8d22da 100644 (file)
@@ -7,10 +7,12 @@
  *
  * Copyright 2010 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
 #include "../mini/jit.h"
+#include "../metadata/metadata-internals.h"
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/threads.h>
 #include <mono/metadata/mono-gc.h>
@@ -2074,10 +2076,11 @@ mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
        do {
                old_data = sbuf->cursor;
                new_data = old_data + SAMPLE_EVENT_SIZE_IN_SLOTS (bt_data.count);
+               if (new_data > sbuf->buf_end)
+                       return; /* Not enough room in buf to hold this event-- lost event */
                data = (uintptr_t *)InterlockedCompareExchangePointer ((void * volatile*)&sbuf->cursor, new_data, old_data);
        } while (data != old_data);
-       if (old_data >= sbuf->buf_end)
-               return; /* lost event */
+
        old_data [0] = 1 | (sample_type << 16) | (bt_data.count << 8);
        old_data [1] = thread_id ();
        old_data [2] = elapsed;
@@ -3770,6 +3773,11 @@ coverage_filter (MonoProfiler *prof, MonoMethod *method)
 
        assembly = mono_image_get_assembly (image);
 
+       // Need to keep the assemblies around for as long as they are kept in the hashtable
+       // Nunit, for example, has a habit of unloading them before the coverage statistics are
+       // generated causing a crash. See https://bugzilla.xamarin.com/show_bug.cgi?id=39325
+       mono_assembly_addref (assembly);
+
        mono_os_mutex_lock (&coverage_mutex);
        mono_conc_hashtable_insert (coverage_methods, method, method);
        mono_conc_hashtable_insert (coverage_assemblies, assembly, assembly);
@@ -3911,6 +3919,13 @@ coverage_init (MonoProfiler *prof)
 #endif /* DISABLE_HELPER_THREAD */
 }
 
+static void
+unref_coverage_assemblies (gpointer key, gpointer value, gpointer userdata)
+{
+       MonoAssembly *assembly = (MonoAssembly *)value;
+       mono_assembly_close (assembly);
+}
+
 static void
 log_shutdown (MonoProfiler *prof)
 {
@@ -3960,6 +3975,10 @@ log_shutdown (MonoProfiler *prof)
        mono_os_mutex_destroy (&prof->method_table_mutex);
 
        if (coverage_initialized) {
+               mono_os_mutex_lock (&coverage_mutex);
+               mono_conc_hashtable_foreach (coverage_assemblies, unref_coverage_assemblies, prof);
+               mono_os_mutex_unlock (&coverage_mutex);
+
                mono_conc_hashtable_destroy (coverage_methods);
                mono_conc_hashtable_destroy (coverage_assemblies);
                mono_conc_hashtable_destroy (coverage_classes);