Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
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
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.
Created attachment 1274 [details]
IL-code that creates two threads that call a synchronized method via "ldftn" and "calli"
In the test case, two threads are started. The threads execute the methods
"jumpStart1()" and "jumpStart2()", respectively. Those methods load a
pointer to the synchronized method "syncMethod()" via "ldftn". That
method is called via "calli" and it increments a static class variable
ten times. So, the expected output is "10" and "20", because the method
"syncMethod()" is synchronized. However, sometimes the output is
"10" and "10". I tested with
Mono-2.6.1 on x86 Linux
Mono-2.8.2 on x86 Linux
Mono-18.104.22.168 on x86 Linux
Mono-2.10.8 on Mac OS X
On .NET, it seems to work because in all test runs the output was "10"
and "20". The test case is compiled by "ilasm thread-ldftn.il" and
executed by "mono thread-ldftn.exe".
If I disable Mono-2.6.1's jump trampoline optimization in
and "mono_post_process_patches()" it seems to work correctly.
I guess, the problem is related to the runtime implementation of the
jump-opcode which is used by the ldftn-opcode: In "mono_postprocess_patches()",
the handle to the method jumped to is stored in the hash table
"jump_target_hash". When a synchronized method is jumped to the
first time, the magic trampoline creates a wrapper and returns
the address of the wrapper. The first jump instruction is patched
with that address.
A later lookup in the "jump_target_hash" ("mono_jit_compile_method_inner()",
in the scope of the JIT-compilation of the wrapper) doesn't return
pending jump patches because the handle of the method to be jumped
to of is stored, instead of the wrapper's handle. So, the second
jump instruction is not patched (if it is JIT-compiled so far).
Fixed in HEAD/2.10.