glib: avoid a delegate to be GCed which caused a NRE (bxc#13113)
What seemed to be a race condition (because of not happenning 100% of the times) ended up being an early garbage collection of a delegate that was still referenced by an unmanaged struct without having a managed counterpart [1]. The consequence of this was a NullReferenceException happening in a line which didn't have a dereference of a null object. The way to reproduce it deterministically 100% of the times was setting the env var MONO_NO_SMP. [1] http://www.mono-project.com/Interop_with_Native_Libraries#Memory_Boundaries
This commit is contained in:
parent
e8f4eca14e
commit
6d626a24a7
2 changed files with 10 additions and 7 deletions
|
@ -1,9 +1,11 @@
|
|||
// GLib.Type.cs - GLib GType class implementation
|
||||
//
|
||||
// Author: Mike Kestner <mkestner@speakeasy.net>
|
||||
// Authors: Mike Kestner <mkestner@speakeasy.net>
|
||||
// Andres G. Aragoneses <knocte@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2003 Mike Kestner
|
||||
// Copyright (c) 2003 Novell, Inc.
|
||||
// Copyright (c) 2013 Andres G. Aragoneses
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of version 2 of the Lesser GNU General
|
||||
|
@ -36,11 +38,10 @@ namespace GLib {
|
|||
|
||||
IntPtr val;
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate void ClassInitDelegate (IntPtr gobject_class_handle);
|
||||
|
||||
struct GTypeInfo {
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
public delegate void ClassInitDelegate (IntPtr gobject_class_handle);
|
||||
|
||||
public ushort class_size;
|
||||
public IntPtr base_init;
|
||||
public IntPtr base_finalize;
|
||||
|
@ -371,7 +372,7 @@ namespace GLib {
|
|||
GTypeInfo info = new GTypeInfo ();
|
||||
info.class_size = (ushort) query.class_size;
|
||||
info.instance_size = (ushort) query.instance_size;
|
||||
info.class_init = gobject_class_initializer.ClassInit;
|
||||
info.class_init = gobject_class_initializer.ClassInitManagedDelegate;
|
||||
|
||||
GType gtype = new GType (g_type_register_static (parent_gtype.Val, native_name, ref info, 0));
|
||||
GLib.Marshaller.Free (native_name);
|
||||
|
|
|
@ -188,6 +188,7 @@ namespace GLib {
|
|||
|
||||
internal Type Type { get; private set; }
|
||||
internal bool HandlersOverriden { get; private set; }
|
||||
internal GType.ClassInitDelegate ClassInitManagedDelegate { get; private set; }
|
||||
|
||||
uint idx = 1;
|
||||
bool is_first_subclass;
|
||||
|
@ -196,6 +197,7 @@ namespace GLib {
|
|||
|
||||
internal ClassInitializer (Type type)
|
||||
{
|
||||
ClassInitManagedDelegate = this.ClassInit;
|
||||
Type = type;
|
||||
gtype = GType.RegisterGObjectType (this);
|
||||
is_first_subclass = gtype.GetBaseType () == gtype.GetThresholdType ();
|
||||
|
@ -231,7 +233,7 @@ namespace GLib {
|
|||
}
|
||||
}
|
||||
|
||||
internal void ClassInit (IntPtr gobject_class_handle)
|
||||
private void ClassInit (IntPtr gobject_class_handle)
|
||||
{
|
||||
bool override_ctor = is_first_subclass;
|
||||
|
||||
|
|
Loading…
Reference in a new issue