Bug 52560 - Exception when use 'mono_jit_cleanup'
Summary: Exception when use 'mono_jit_cleanup'
Alias: None
Product: Runtime
Classification: Mono
Component: JIT (show other bugs)
Version: 4.6.0 (C8)
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2017-02-16 08:49 UTC by Shui
Modified: 2017-10-06 23:01 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

C#/C++ Code (1.40 KB, application/zip)
2017-02-16 08:49 UTC, Shui

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Shui 2017-02-16 08:49:22 UTC
Created attachment 19841 [details]
C#/C++ Code

Version: Mono JIT compiler version 4.6.2
Use a C++ program call C# method in dll (Embedding mono).
If the method needs an array as parameter. At the end of C++, when 'mono_jit_cleanup' was called, it gives an exception.
If we call a method without array parameter, 'mono_jit_cleanup' works without exception.

How to reproduce the exception:
Step 1: Compile the C# Code (using cmd "mcs /out:TestArrayCSharp.dll /target:library TestArrayCSharp.cs")
Step 2: Compile the C++ Code (using cmd "g++ hello.cpp -g3 `pkg-config --cflags --libs mono-2` -o hello
Step 3: Execute the program (using cmd "./hello")

Then we can get the exception:

Native stacktrace:

	/lib64/libmonosgen-2.0.so.1(+0xe3a5c) [0x7f5d07d5da5c]
	/lib64/libmonosgen-2.0.so.1(+0x13fcde) [0x7f5d07db9cde]
	/lib64/libmonosgen-2.0.so.1(+0x47df3) [0x7f5d07cc1df3]
	/lib64/libpthread.so.0(+0xf370) [0x7f5d07661370]
	/lib64/libmonosgen-2.0.so.1(+0x248df5) [0x7f5d07ec2df5]
	/lib64/libmonosgen-2.0.so.1(+0x236b72) [0x7f5d07eb0b72]
	/lib64/libmonosgen-2.0.so.1(+0x2379b0) [0x7f5d07eb19b0]
	/lib64/libmonosgen-2.0.so.1(+0x237da9) [0x7f5d07eb1da9]
	/lib64/libmonosgen-2.0.so.1(+0x23a88f) [0x7f5d07eb488f]
	/lib64/libmonosgen-2.0.so.1(+0x23ad5d) [0x7f5d07eb4d5d]
	/lib64/libmonosgen-2.0.so.1(mono_domain_finalize+0x8c) [0x7f5d07e6c35c]
	/lib64/libmonosgen-2.0.so.1(+0x44ce9) [0x7f5d07cbece9]
	./hello(main+0x2a2) [0x40120f]
	/lib64/libc.so.6(__libc_start_main+0xf5) [0x7f5d06a91b35]
	./hello() [0x400ea9]

Debug info from gdb:

[New LWP 49516]
[New LWP 49515]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x00007f5d07660f19 in waitpid () from /lib64/libpthread.so.0
  Id   Target Id         Frame 
  3    Thread 0x7f5d063ff700 (LWP 49515) "SGen worker" 0x00007f5d0765d6d5 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  2    Thread 0x7f5d06a6f700 (LWP 49516) "Finalizer" 0x00007f5d0765f79b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
* 1    Thread 0x7f5d08466780 (LWP 49514) "hello" 0x00007f5d07660f19 in waitpid () from /lib64/libpthread.so.0

Thread 3 (Thread 0x7f5d063ff700 (LWP 49515)):
#0  0x00007f5d0765d6d5 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f5d07ed1463 in mono_os_cond_wait (mutex=0x7f5d08240700 <lock>, cond=0x7f5d082406c0 <work_cond>) at ../../mono/utils/mono-os-mutex.h:107
#2  thread_func (thread_data=0x0) at sgen-thread-pool.c:110
#3  0x00007f5d07659dc5 in start_thread () from /lib64/libpthread.so.0
#4  0x00007f5d06b6773d in clone () from /lib64/libc.so.6

Thread 2 (Thread 0x7f5d06a6f700 (LWP 49516)):
#0  0x00007f5d0765f79b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1  0x00007f5d0765f82f in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2  0x00007f5d0765f8cb in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3  0x00007f5d07e6bdbf in mono_os_sem_wait (flags=MONO_SEM_FLAGS_ALERTABLE, sem=0x7f5d082315a0 <finalizer_sem>) at ../../mono/utils/mono-os-semaphore.h:166
#4  mono_coop_sem_wait (sem=0x7f5d082315a0 <finalizer_sem>, flags=MONO_SEM_FLAGS_ALERTABLE) at ../../mono/utils/mono-coop-semaphore.h:40
#5  finalizer_thread (unused=unused@entry=0x0) at gc.c:761
#6  0x00007f5d07e4a6ad in start_wrapper_internal (data=<optimized out>) at threads.c:740
#7  start_wrapper (data=<optimized out>) at threads.c:788
#8  0x00007f5d07f034da in inner_start_thread (arg=<optimized out>) at mono-threads-posix.c:92
#9  0x00007f5d07659dc5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007f5d06b6773d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f5d08466780 (LWP 49514)):
#0  0x00007f5d07660f19 in waitpid () from /lib64/libpthread.so.0
#1  0x00007f5d07d5db1c in mono_handle_native_sigsegv (signal=signal@entry=11, ctx=ctx@entry=0x7f5d08472ac0, info=info@entry=0x7f5d08472bf0) at mini-exceptions.c:2427
#2  0x00007f5d07db9cde in mono_arch_handle_altstack_exception (sigctx=sigctx@entry=0x7f5d08472ac0, siginfo=siginfo@entry=0x7f5d08472bf0, fault_addr=<optimized out>, stack_ovf=stack_ovf@entry=0) at exceptions-amd64.c:795
#3  0x00007f5d07cc1df3 in mono_sigsegv_signal_handler (_dummy=11, _info=0x7f5d08472bf0, context=0x7f5d08472ac0) at mini-runtime.c:2865
#4  <signal handler called>
#5  major_copy_or_mark_object_no_evacuation (queue=0x7f5d0823ce80 <gray_queue>, obj=0xbe4ccccdbf000000, ptr=0x7f5d0640b478) at sgen-marksweep-drain-gray-stack.h:52
#6  major_scan_object_no_evacuation (queue=0x7f5d0823ce80 <gray_queue>, desc=<optimized out>, full_object=<optimized out>) at sgen-scan-object.h:56
#7  drain_gray_stack_no_evacuation (queue=<optimized out>) at sgen-marksweep-drain-gray-stack.h:309
#8  drain_gray_stack (queue=<optimized out>) at sgen-marksweep.c:1217
#9  0x00007f5d07eb0b72 in finish_gray_stack (generation=generation@entry=1, ctx=...) at sgen-gc.c:1074
#10 0x00007f5d07eb19b0 in major_finish_collection (reason=reason@entry=0x7f5d07fa7e75 "user request", is_overflow=is_overflow@entry=0, old_next_pin_slot=17, forced=forced@entry=1) at sgen-gc.c:1957
#11 0x00007f5d07eb1da9 in major_do_collection (reason=0x7f5d07fa7e75 "user request", is_overflow=0, forced=1) at sgen-gc.c:2083
#12 0x00007f5d07eb488f in sgen_perform_collection (requested_size=0, generation_to_collect=1, reason=0x7f5d07fa7e75 "user request", wait_to_finish=1, stw=1) at sgen-gc.c:2279
#13 0x00007f5d07eb4d5d in sgen_gc_collect (generation=1) at sgen-gc.c:2692
#14 0x00007f5d07ea6775 in mono_gc_collect (generation=<optimized out>) at sgen-mono.c:2555
#15 0x00007f5d07e6c35c in mono_domain_finalize (domain=domain@entry=0x1b19420, timeout=timeout@entry=2000) at gc.c:413
#16 0x00007f5d07cbece9 in mini_cleanup (domain=0x1b19420) at mini-runtime.c:4046
#17 0x000000000040120f in main (argc=1, argv=0x7ffd84b2f468) at hello.cpp:48

Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.

Aborted (core dumped)

C# Code: 
using System;
using System.Collections.Generic;

namespace TestArrayCSharp

    public class TestArray
        public TestArray()
		Console.WriteLine ("TestArray: constructor");

	public float Sum (float[] values)
		float sum = 0;
		foreach(float v in values)
			sum += v;

		Console.WriteLine("Just before return, sum = " + sum);
		return sum;
C++ Code:
using namespace std;
#include <iostream>
#include <mono/jit/jit.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/debug-helpers.h>

int main(int argc, char* argv[]) {

  MonoDomain* domain = mono_jit_init("TestArrayCSharp.dll");
  MonoAssembly* assembly = mono_domain_assembly_open(domain, "TestArrayCSharp.dll");
  MonoImage* image = mono_assembly_get_image(assembly);
  MonoClass* entityClass = mono_class_from_name(image, "TestArrayCSharp", "TestArray");
  MonoObject* entityInstance = mono_object_new(domain, entityClass);

mono_domain_set_config(domain, (char *)"../Test_Array", (char *)"blabla.dll.config");

  MonoMethod* ctorMethod = mono_class_get_method_from_name(entityClass, ".ctor", 0);
  mono_runtime_invoke(ctorMethod, entityInstance, NULL, NULL);

printf("Methode Sum\n");
  float values [] = {-0.5f, -0.2f, 0.2f, 0.5f, 1.0f, 2.1f, 3.0f};
  int arrayLength = sizeof(values)/sizeof(values[0]);
  MonoArray* array = mono_array_new(domain, entityClass, arrayLength);
  for(int index = 0; index < arrayLength; index++)
      mono_array_set(array, float, index, values[index]);
  void* args[1];
  args[0] = array;
  //Print array for test
  printf("Print array for test\n");
  for(int index = 0; index < arrayLength; index++)
      float monoFloat = mono_array_get(array, float, index);
      cout << monoFloat << ";";
  cout << endl;

  MonoMethod* doSumMethod = mono_class_get_method_from_name(entityClass, "Sum", 1);

  MonoObject* monoReturn = mono_runtime_invoke(doSumMethod, entityInstance, args, NULL);

  float sum = *(float*)mono_object_unbox (monoReturn);
  cout << "Result is " << sum << endl;

Comment 1 Ludovic Henry 2017-10-06 23:01:48 UTC
The bug is in your code: 

1. you create `array = mono_array_new(domain, entityClass, arrayLength)` which is equivalent to the C# code `array = new TestArray[]`
2. you do `mono_array_set(array, float, index, values[index])` which is equivalent to the C# code `array[index] = values[index]` but that is impossible as array is of type `TestArray[]` and values is of type `float[]`.

The crash you are observing is a GC crash as it tries to scan `array`, which should contains objects of type `TestArray` but it contains float values.