Bug 13113 - NullReferenceException is thrown in a line in which it should not happen (assignment of a bool value)
Summary: NullReferenceException is thrown in a line in which it should not happen (ass...
Status: RESOLVED FIXED
Alias: None
Product: Gtk#
Classification: Mono
Component: gtk-sharp ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-07-09 05:51 UTC by Andres G. Aragoneses
Modified: 2013-07-23 12:35 UTC (History)
4 users (show)

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


Attachments
For reference, this was the old locking patch that I thought was the correct fix, before Zoltan posted comment#1 (4.51 KB, patch)
2013-07-17 08:14 UTC, Andres G. Aragoneses
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 Andres G. Aragoneses 2013-07-09 05:51:45 UTC
I have detected what I thought it was a race condition when interoperating with unmanaged code (and so I thought this strange situation was causing a memory corruption which could lead to the runtime to report an exception in a strange place).

The fact that led me to think it was a race condition was that I couldn't reproduce the problem with a computer with 2 cores or less, and I could reproduce it with one with 4 cores (about 20% of the times I ran the testcase).

However, after some more digging, testing my code with MONO_NO_SMP=1 set, it turns out that the race condition is hit 100% of the times (which seems even more strange because I thought MONO_NO_SMP set would cause the opposite situation: to never expose race conditions).

The testcase is the following:
1. Build & install gtk-sharp master.
2. Go to sample/ dir and run "mono custom-scrollable
The exception is:

$ MONO_NO_SMP=1 mono --debug custom-scrollable.exe

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
  at GLib.Object+ClassInitializer.ClassInit (IntPtr gobject_class_handle) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:236 
  at (wrapper managed-to-native) GLib.GType:g_type_class_ref (intptr)
  at GLib.GType.EnsureClass () [0x0001b] in /home/knocte/Documents/Code/gtk-sharp/glib/GType.cs:335 
  at GLib.Object+ClassInitializer.Init () [0x00007] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:207 
  at GLib.Object.RegisterGType (System.Type t) [0x0000d] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:556 
  at GLib.GType.LookupGObjectType (System.Type t) [0x00063] in /home/knocte/Documents/Code/gtk-sharp/glib/GType.cs:394 
  at GLib.Object.LookupGType (System.Type t) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:572 
  at GLib.Object.LookupGType () [0x00061] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:566 
  at GLib.Object.CreateNativeObject (System.String[] names, GLib.Value[] vals) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:598 
  at Gtk.Widget.CreateNativeObject (System.String[] names, GLib.Value[] vals) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/gtk/Widget.cs:374 
  at Gtk.Widget..ctor () [0x0000c] in /home/knocte/Documents/Code/gtk-sharp/gtk/generated/Widget.cs:19 
  at CustomBase..ctor () [0x00000] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:46 
  at CustomScrollableWidget`1[System.Object]..ctor (System.String custom_label) [0x00008] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:61 
  at DerivedScrollableWidget`1[System.Object]..ctor (System.String label) [0x00000] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:52 
  at CustomScrollableWidgetTest.Main (System.String[] args) [0x0006c] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:26 
[ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
  at GLib.Object+ClassInitializer.ClassInit (IntPtr gobject_class_handle) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:236 
  at (wrapper managed-to-native) GLib.GType:g_type_class_ref (intptr)
  at GLib.GType.EnsureClass () [0x0001b] in /home/knocte/Documents/Code/gtk-sharp/glib/GType.cs:335 
  at GLib.Object+ClassInitializer.Init () [0x00007] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:207 
  at GLib.Object.RegisterGType (System.Type t) [0x0000d] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:556 
  at GLib.GType.LookupGObjectType (System.Type t) [0x00063] in /home/knocte/Documents/Code/gtk-sharp/glib/GType.cs:394 
  at GLib.Object.LookupGType (System.Type t) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:572 
  at GLib.Object.LookupGType () [0x00061] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:566 
  at GLib.Object.CreateNativeObject (System.String[] names, GLib.Value[] vals) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/glib/Object.cs:598 
  at Gtk.Widget.CreateNativeObject (System.String[] names, GLib.Value[] vals) [0x00001] in /home/knocte/Documents/Code/gtk-sharp/gtk/Widget.cs:374 
  at Gtk.Widget..ctor () [0x0000c] in /home/knocte/Documents/Code/gtk-sharp/gtk/generated/Widget.cs:19 
  at CustomBase..ctor () [0x00000] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:46 
  at CustomScrollableWidget`1[System.Object]..ctor (System.String custom_label) [0x00008] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:61 
  at DerivedScrollableWidget`1[System.Object]..ctor (System.String label) [0x00000] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:52 
  at CustomScrollableWidgetTest.Main (System.String[] args) [0x0006c] in /home/knocte/Documents/Code/gtk-sharp/sample/CustomScrollableWidget.cs:26 
knocte@ulises:~/Documents/Code/gtk-sharp/sample$ 


The line that is said to throw the NRE is:

https://github.com/mono/gtk-sharp/blob/master/glib/Object.cs#l236
Comment 1 Zoltan Varga 2013-07-16 19:44:02 UTC
Looking at the code in GType.cs, there is this line:

info.class_init = gobject_class_initializer.ClassInit;

What this does is create a delegate, and put it into a structure which is passed to native code, but there is no managed reference for the delegate, so it will be garbage collected, and when the native code tries to call this delegate, something random will happen like this nullref.
See:
http://www.mono-project.com/Interop_with_Native_Libraries#Memory_Boundaries
Comment 2 Andres G. Aragoneses 2013-07-17 08:11:21 UTC
Wow, seems strange that a delegate to a non-static method of an object that hasn't been collected yet, could be collected! Are you sure this is the same behaviour in the MS.NET runtime?

Anyway, following your advice I have created a managed counterpart, tested it (it works), and proposed a pull request:

https://github.com/mono/gtk-sharp/pull/63
Comment 3 Andres G. Aragoneses 2013-07-17 08:14:42 UTC
Created attachment 4357 [details]
For reference, this was the old locking patch that I thought was the correct fix, before Zoltan posted comment#1
Comment 4 Zoltan Varga 2013-07-17 10:13:29 UTC
A delegate is a separate object, it can be collected by itself.
Comment 5 Bertrand Lorentz 2013-07-23 12:21:26 UTC
Thanks for the pull request Andrés.
I've merged it into git master, so I guess this can be closed (I can't do it myself).
Comment 6 Andres G. Aragoneses 2013-07-23 12:35:38 UTC
Thanks for the merge!

>A delegate is a separate object, it can be collected by itself.

Fair enough. BTW, given that the native struct points to a memory address which is not valid anymore (because the GC has freed it), I'm guessing the exception that the runtime should throw an AccessViolationException instead of a NullReferenceException? I think I've seen this difference with MS.NET in other places. Let me know if you want me to open it as a different bug.