+2010-04-02 Miguel de Icaza <miguel@novell.com>
+
+ * SafeHandle.cs: Use refcount == -1 to indicate that the handle
+ had been closed.
+
+ The problem here is that we have no records of why the code that
+ threw a ObjectDisposedException inside the do { } while block on
+ DangerousAddRef was added. It seems it was added in response to
+ Close() methods being called and the need to throw that exception
+ on further calls to ObjectDisposedException.
+
+ Sadly, we have no test suites for that.
+
2010-03-16 Jb Evain <jbevain@novell.com>
* MarshalAsAttribute.cs, Marshal.cs: use MOONLIGHT symbol to
if (newcount == 0 && owns_handle && !IsInvalid){
ReleaseHandle ();
handle = invalid_handle_value;
+ refcount = -1;
}
}
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
public void DangerousAddRef (ref bool success)
{
- if (refcount == 0)
+ if (refcount <= 0)
throw new ObjectDisposedException (GetType ().FullName);
int newcount, current;
current = refcount;
newcount = current + 1;
- if (handle == invalid_handle_value || current == 0){
+ if (current <= 0){
//
// In MS, calling sf.Close () followed by a call
// to P/Invoke with SafeHandles throws this, but
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
public IntPtr DangerousGetHandle ()
{
- if (refcount == 0){
+ if (refcount <= 0){
throw new ObjectDisposedException (GetType ().FullName);
}
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
public void DangerousRelease ()
{
- if (refcount == 0)
+ if (refcount <= 0)
throw new ObjectDisposedException (GetType ().FullName);
int newcount, current;
public bool IsClosed {
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
get {
- return refcount == 0;
+ return refcount <= 0;
}
}
((IDisposable) sf).Dispose ();
Assert.AreEqual (sf.released, false, "r3");
}
+
+ //
+ // This test does a DangerousAddRef on a new instance
+ // of a custom user Safe Handle, and it just happens
+ // that the default value for the handle is an invalid
+ // handle.
+ //
+ // .NET does not throw an exception in this case, so
+ // we should not either
+ //
+ [Test]
+ public void DangerousAddRefOnNewInstance ()
+ {
+ var h = new IntPtrSafe ();
+ var success = false;
+ h.DangerousAddRef (ref success);
+ Assert.AreEqual (success, true, "daroni");
+ }
+
+ public class IntPtrSafe : SafeHandle {
+ public IntPtrSafe() : base(IntPtr.Zero, true)
+ {
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ return true;
+ }
+
+ public IntPtr Handle { get; set; }
+
+ public override bool IsInvalid
+ {
+ get { return Handle == IntPtr.Zero; }
+ }
+ }
}
}