[Mono-dev] Double/redundant release of COM object while marshaling from IUnknown (with patch)
Ivo Smits
Ivo at UFO-Net.nl
Tue Apr 26 16:04:39 EDT 2011
While working on an interface between VirtualBox and C# on Linux, I ran
into a problem, which I think may be a bug in the mono code.
The System.Runtime.InteropServices.Marshal.GetObjectForIUnknown function
releases (using Marshal.Release) the given COM pointer. Microsoft's
documentation does not speak about such behaviour. The reference count
should instead be incremented and only get decremented when the proxy is
garbage collected. The result is that for consecutive calls to
GetObjectForIUnknown on the same pointer, the second call fails, as the
COM object has been released (and may have been destructed!) by the
first call. Also, when Marshaling an output/return parameter of a COM
interop function, the COM pointer is released in the interop code as
well - after calling GetObjectForIUnknown. This results in a
double/redundant Release of the COM object, which leads to crashes.
I am not sure about the correct behaviour, and how well the current code
has been tested. I've patched mono (from git) to work with my code, the
diff is listed below. I have removed both calls to Marshal.Release in
the GetObjectForIUnknown function. I am not sure about the purpose of
the interlocked increment; Marshal.AddRef should be used for COM
reference counting.
--
Ivo
diff --git a/mcs/class/corlib/Mono.Interop/ComInteropProxy.cs
b/mcs/class/corlib/Mono.Interop/ComInteropProxy.cs
index 54fefe2..1271257 100644
--- a/mcs/class/corlib/Mono.Interop/ComInteropProxy.cs
+++ b/mcs/class/corlib/Mono.Interop/ComInteropProxy.cs
@@ -93,12 +93,9 @@ namespace Mono.Interop
Marshal.ThrowExceptionForHR (hr);
ComInteropProxy obj = FindProxy (ppv);
if (obj == null) {
- Marshal.Release (pItf);
return new ComInteropProxy (ppv);
}
else {
- Marshal.Release (pItf);
- System.Threading.Interlocked.Increment
(ref obj.ref_count);
return obj;
}
}
More information about the Mono-devel-list
mailing list