[Mono-dev] Question about System_ComObject_ReleaseInterfaces in mono/metadata/cominterop.c
Tom Hindle
tom_hindle at sil.org
Wed Apr 29 12:58:18 EDT 2009
Hi,
Whilst attempting to make mono tell me when Com objects are used, after
they have been released - for example:
IComObject i = new CplusplusComObject()
IComObject j = i;
Marshal.ReleaseComObject(i);
j.SomeMethod();
(which incidentally in this situation .Net throws the following
exception:
System.AccessViolationException : Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.
I NOT advocating changing mono to do this due lack of usefulness because
of the unpredictability of this way of doing things.
)
So I was looking to see if one could tell when MonoComObject was used if
it had been released yet.
I found that that checking MonoComObject.itf_hash if it was null wasn't
enough as presumably it can be null before the object is first
used/fully initialized.
So I tried checking both MonoComObject.itf_hash &&
MonoComObject.iunknown for NULL ( which worked better)
However I seem to run into situations that iunknown was non NULL after
deletion.
On examining System_ComObject_ReleaseInterfaces method, it seems that if
Release is called on a ComObject that hasn't had its obj->itf_hash
initialized then iunknown is not null'ed.
void
ves_icall_System_ComObject_ReleaseInterfaces (MonoComObject* obj)
{
g_assert(obj);
if (obj->itf_hash) {
guint32 gchandle = 0;
mono_cominterop_lock ();
gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (rcw_hash,
obj->iunknown));
if (gchandle) {
mono_gchandle_free (gchandle);
g_hash_table_remove (rcw_hash, obj->iunknown);
}
g_hash_table_foreach_remove (obj->itf_hash,
cominterop_rcw_interface_finalizer, NULL);
g_hash_table_destroy (obj->itf_hash);
ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal
(obj->iunknown);
obj->itf_hash = obj->iunknown = NULL;
mono_cominterop_unlock ();
}
}
So I added which I added the following:
else /* obj->itf_hash is null */
{
mono_cominterop_lock ();
obj->iunknown = NULL;
mono_cominterop_unlock ();
}
This solved my problem in detecting com object being used from C# after
they had been released.
but interestingly it also solved some crash on exit bugs I was seeing
when running our unit tests on Linux. It also caused my application I am
porting not to frequently segfault on exit.
Could anyone tell me if my modification to
System_ComObject_ReleaseInterfaces is sensible/stupid/other?
Thanks for your help!
Tom
More information about the Mono-devel-list
mailing list