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)

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

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

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.

Note You need to log in before you can comment on or make changes to this bug.