[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