Bug 2759 - Mono.Tasklets segfault on x86
Summary: Mono.Tasklets segfault on x86
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: General ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-01-06 09:14 UTC by Tristan Caulfield
Modified: 2012-01-14 13:05 UTC (History)
4 users (show)

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


Attachments
patch to fix crash (2.04 KB, patch)
2012-01-11 11:53 UTC, Tristan Caulfield
Details


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:
Status:
RESOLVED FIXED

Description Tristan Caulfield 2012-01-06 09:14:06 UTC
Using mono 2.10.8 on x86.

Running this test program (mono --debug TestContinuation.exe)

using Mono.Tasklets;
namespace TestContinuation
{	
    class MainClass
    {
        public static void Main (string[] args)
        {					
            var c = new Continuation();
            c.Mark();			
            System.Console.WriteLine("Done");
        }
    }
}

results in an segfault in mono_unwind_frame, unwind.c:401.

This does not occur on amd64 or on x86 in version 2.10.2.
Running with --no-x86-stack-align does not segfault.

Here is the stack trace:

Thread 1 (Thread 0xb78b6b40 (LWP 25249)):
#0  0x004bb422 in __kernel_vsyscall ()
#1  0x00898f5b in read () from /lib/tls/i686/cmov/libpthread.so.0
#2  0x080e0673 in read (signal=11, ctx=0xb5f49d0c) at /usr/include/bits/unistd.h:45
#3  mono_handle_native_sigsegv (signal=11, ctx=0xb5f49d0c) at mini-exceptions.c:2208
#4  0x08123e3b in mono_arch_handle_altstack_exception (sigctx=0xb5f49d0c, fault_addr=0x0, stack_ovf=0) at exceptions-x86.c:1223
#5  0x0805bf41 in mono_sigsegv_signal_handler (_dummy=11, info=0xb5f49c8c, context=0xb5f49d0c) at mini.c:5909
#6  <signal handler called>
#7  0x080f0bae in mono_unwind_frame (unwind_info=0x90dd274 "\f\004\004\210\001A\016\b\205\002B\r\005G\206\005A\207\006A\203\a\r\t!", 
    unwind_info_len=22, start_ip=0x3b82c0 "U\213\354hĂ;", end_ip=0x3b832a "", ip=<value optimised out>, regs=0xbfdc5950, nregs=9, save_locations=
    0x0, save_locations_len=8, out_cfa=0xbfdc5978) at unwind.c:401
#8  0x08124400 in mono_arch_find_jit_info (domain=0x34e58, jit_tls=0x9073588, ji=0x9101d44, ctx=0xbfdc5b0c, new_ctx=0xbfdc5ae8, lmf=0xbfdc5b4c, 
    save_locations=0x0, frame=<value optimised out>) at exceptions-x86.c:788
#9  0x080e07b3 in find_jit_info (domain=0x34e58, jit_tls=<value optimised out>, res=0xbfdc5b30, prev_ji=0x0, ctx=0xbfdc5b0c, new_ctx=0xbfdc5ae8, 
    lmf=0xbfdc5b4c, managed=0xbfdc5a7c) at mini-exceptions.c:215
#10 0x080e0936 in mono_find_jit_info (domain=0x34e58, jit_tls=0x9073588, res=0xbfdc5b30, prev_ji=0x0, ctx=0xbfdc5b0c, new_ctx=0xbfdc5ae8, trace=
    0x0, lmf=0xbfdc5b4c, native_offset=0x0, managed=0x0) at mini-exceptions.c:277
#11 0x080ec501 in continuation_mark_frame (cont=0x9119028) at tasklets.c:65
#12 0x003b82f0 in ?? ()
#13 0x003b8298 in ?? ()
#14 0x003adde4 in ?? ()
#15 0x003ade97 in ?? ()
#16 0x08062d28 in mono_jit_runtime_invoke (method="TestContinuation.MainClass:Main ()", obj=0x0, params=0xbfdc5ccc, exc=0x0) at mini.c:5791
#17 0x081c36b0 in mono_runtime_invoke (method="TestContinuation.MainClass:Main ()", obj=0x0, params=0xbfdc5ccc, exc=0x0) at object.c:2755
#18 0x081c7396 in mono_runtime_exec_main (method="TestContinuation.MainClass:Main ()", args=0x3be00, exc=0x0) at object.c:3938
#19 0x080bb535 in main_thread_handler (argc=3, argv=0xbfdc5eb4) at driver.c:1003
#20 mono_main (argc=3, argv=0xbfdc5eb4) at driver.c:1855
#21 0x0805948a in mono_main_with_options (argc=3, argv=0xbfdc5eb4) at main.c:66
#22 main (argc=3, argv=0xbfdc5eb4) at main.c:97
Comment 1 Tristan Caulfield 2012-01-08 23:03:32 UTC
I upgraded to a newer version of GCC (4.6.2 now, was < 4.5 before) and the original test case above works now correctly.  However, I still encounter the same error in a larger program, but I have not yet been able to construct a small example program that replicates it.

I did encounter another problem, which this test program illustrates:

using Mono.Tasklets;
using System;

namespace TestContinuation
{	
	class MainClass
	{
		
		class TestThread {
			public Continuation c = null;
			public int id;
			
			public void Run() {	
#if RUN_CORRECTLY
				Console.WriteLine("Run   - " + id);
#endif
				int i = 10;				
				while(i > 0) {
					i--;
					Sleep(this);
				}				
			}
			
		}
		
		static TestThread[] threads = new TestThread[5];
		static int curIndex;
		
		static Continuation cont;
		
		static void Sleep(TestThread tt) {
			
			int r = tt.c.Store(1);
			if(r == 1) {
				curIndex++;
				if(curIndex == threads.Length) {
					curIndex  = 0;
				}
				
				Console.WriteLine("Sleep - " + tt.id);
				cont.Restore(1);
			} else {
				Console.WriteLine("Wake  - " + tt.id);
			}
			
		}
		
		public static void Main (string[] args)
		{					
			
			for(int i = 0; i < threads.Length; i++) {
				threads[i] = new TestThread();	
				threads[i].id = i;
			}
			
			cont = new Continuation();
			cont.Mark();
			
			curIndex = 0;
			
			cont.Store(1);
			
			if( threads[curIndex].c == null) {
				threads[curIndex].c = new Continuation();
				threads[curIndex].c.Mark();
				threads[curIndex].Run();
			} else  {
				threads[curIndex].c.Restore(2);
			}
			
			Console.WriteLine("Done");
		}
		
	}
}

On amd64, running the program gives output:

Sleep - 0
Sleep - 1
Sleep - 2
Sleep - 3
Sleep - 4
Wake  - 0
Sleep - 0
Wake  - 1
Sleep - 1
Wake  - 2
Sleep - 2
Wake  - 3
Sleep - 3
Wake  - 4
Sleep - 4
Wake  - 0
... etc, etc, etc.
Done

On x86 the output is the following:
Sleep - 0
Sleep - 1
Sleep - 2
Sleep - 3
Sleep - 4
Sleep - 0
Sleep - 1
Sleep - 2
Sleep - 3
Sleep - 4
Sleep - 0
Sleep - 1
Sleep - 2
Sleep - 3
Sleep - 4
Sleep - 0
... continues infinitely

If you #define RUN_CORRECTLY, then the program runs correctly.

The value returned when the Continuation is restored is being lost.
Comment 2 Tristan Caulfield 2012-01-11 11:53:47 UTC
Created attachment 1166 [details]
patch to fix crash

* Fix mono_tasklets_arch_restore in exceptions-x86.c so it moves return value to $eax before overwriting the stack.

* Fix continuation_store in tasklets.c so that it sets cont->stack_used_size if the size of the saved stack becomes smaller.
Comment 3 Zoltan Varga 2012-01-14 13:05:14 UTC
Applied to master/2.10.