[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