[Mono-dev] [Mono-gc-list] Mono memory problems!

Cedric Vivier cedricv at neonux.com
Wed Jul 18 16:33:19 EDT 2007


On 7/18/07, I wrote :
> > Looks like the _wapi_private_handles array expands indefinitely but
> > never shrinks.
>
> Hmm, by "shrinks" I meant the allocated slots are not reused like they
> should because of the Close() I guess.

I've continued my investigation from the low-level handles.c to the managed.

If you trace the testcase you'll get this.

. . . . . ENTER: System.Runtime.InteropServices.SafeHandle:Dispose
(bool)(this:0x82953c0[Microsoft.Win32.SafeHandles.SafeWaitHandle
leak-bad.exe], 1, )
. . . . . . ENTER: System.Runtime.InteropServices.SafeHandle:Close
()(this:0x82953c0[Microsoft.Win32.SafeHandles.SafeWaitHandle
leak-bad.exe], )
. . . . . . . ENTER: (wrapper managed-to-native)
System.Threading.Interlocked:CompareExchange
(int&,int,int)([BYREF:0x82953d0], 0, 1, )
. . . . . . . LEAVE: (wrapper managed-to-native)
System.Threading.Interlocked:CompareExchange (int&,int,int)result=1
**************** Here we should actually call ReleaseHandle() !
. . . . . . LEAVE: System.Runtime.InteropServices.SafeHandle:Close ()
. . . . . LEAVE: System.Runtime.InteropServices.SafeHandle:Dispose (bool)

ReleaseHandle does not get called because the handle is wrapped into
SafeHandle with ownsHandle = false.

This leaky behavior was actually "forecasted" in a visionnary comment
in System.Threading/WaitHandle.cs 2.0 region :

// Notice, from the 2.x documentation:
//    Assigning a new value to the Handle property, will not release
//    the previous handle, this could lead to a leak
safe_wait_handle = new SafeWaitHandle (value, false);

Replace false by true, problem solved?
Nope, because then ReleaseHandle() from SafeWaitHandle throws an
ObjectDisposed exception because concrete WaitHandle.ReleaseHandle()
call the native Close_event with GetDangerousHandle() as argument,
though the refcount has been set to 0 earlier in Dispose().
I'm not sure it would be wise to change the real refcount field in
Close() after the ReleaseHandle() either because of potential race
conditions (?), so in GetDangerousHandle() another way is to check
moreover the refcount if the handle is invalid as set by Close() after
the handle release anyway.

Attached tentative patch fixes the memory leak :)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SafeWaitHandle_leak.patch
Type: text/x-patch
Size: 1346 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20070718/9743f6e0/attachment.bin 


More information about the Mono-devel-list mailing list