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:
Andrés G. Aragoneses 2013-07-17 14:24:02 +02:00
parent e8f4eca14e
commit 6d626a24a7
2 changed files with 10 additions and 7 deletions

View File

@ -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);

View File

@ -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;