From cb100fb167e5ba113679db86ae49553ba2b5e7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Wed, 1 Dec 2010 15:54:26 +0000 Subject: [PATCH 1/3] [SafeHandle] Protect Close against asynchronous exceptions --- .../SafeHandle.cs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs index e1b0a70ffb24..330e8aa2b560 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs @@ -46,6 +46,7 @@ using System; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; +using System.Runtime.CompilerServices; using System.Threading; namespace System.Runtime.InteropServices @@ -81,16 +82,26 @@ public void Close () if (refcount == 0) throw new ObjectDisposedException (GetType ().FullName); - int newcount, current; - do { - current = refcount; - newcount = current-1; - } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current); - - if (newcount == 0 && owns_handle && !IsInvalid){ - ReleaseHandle (); - handle = invalid_handle_value; - refcount = -1; + int newcount = 0, current = 0; + bool registered = false; + RuntimeHelpers.PrepareConstrainedRegions (); + try { + do { + current = refcount; + newcount = current-1; + + try {} + finally { + if (Interlocked.CompareExchange (ref refcount, newcount, current) == current) + registered = true; + } + } while (!registered); + } finally { + if (registered && newcount == 0 && owns_handle && !IsInvalid){ + ReleaseHandle (); + handle = invalid_handle_value; + refcount = -1; + } } } From b07b00e2a145f323eaa696b02a4336ad5aaed5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Wed, 1 Dec 2010 15:54:48 +0000 Subject: [PATCH 2/3] [SafeHandle] Make success parameter setting atomic wrt async exception in DangerousAddRef --- .../System.Runtime.InteropServices/SafeHandle.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs index 330e8aa2b560..6d03daa69368 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs @@ -120,6 +120,7 @@ public void DangerousAddRef (ref bool success) if (refcount <= 0) throw new ObjectDisposedException (GetType ().FullName); + bool registered = false; int newcount, current; do { current = refcount; @@ -134,8 +135,14 @@ public void DangerousAddRef (ref bool success) // throw new ObjectDisposedException (GetType ().FullName); } - } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current); - success = true; + + RuntimeHelpers.PrepareConstrainedRegions (); + try {} + finally { + if (Interlocked.CompareExchange (ref refcount, newcount, current) == current) + registered = success = true; + } + } while (!registered); } [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)] From 72d878ce899414648d927bbae57eefccc74b2d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Wed, 1 Dec 2010 19:52:42 +0000 Subject: [PATCH 3/3] [SafeHandle] Add bits of documentation --- .../corlib/System.Runtime.InteropServices/SafeHandle.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs index 6d03daa69368..ed0663963954 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs @@ -30,12 +30,14 @@ // For details, see: // http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx // +// CER-like behavior is implemented for Close and DangerousAddRef +// via the try/finally uninterruptible pattern in case of async +// exceptions like ThreadAbortException. +// // On implementing SafeHandles: // http://blogs.msdn.com/bclteam/archive/2005/03/15/396335.aspx // // Issues: -// The System.Runtime.ConstrainedExecution.ReliabilityContractAttribute has -// not been applied to any APIs here yet. // // TODO: Although DangerousAddRef has been implemented, I need to // find out whether the runtime performs the P/Invoke if the @@ -90,6 +92,7 @@ public void Close () current = refcount; newcount = current-1; + // See notes for explanation try {} finally { if (Interlocked.CompareExchange (ref refcount, newcount, current) == current) @@ -136,6 +139,7 @@ public void DangerousAddRef (ref bool success) throw new ObjectDisposedException (GetType ().FullName); } + // See notes for explanations RuntimeHelpers.PrepareConstrainedRegions (); try {} finally {