Skip to content

Commit ab504ef

Browse files
authored
SqlDependencyProcessDispatcherStorage lock fix, use intptr (#3208)
1 parent a22bf28 commit ab504ef

File tree

1 file changed

+13
-27
lines changed

1 file changed

+13
-27
lines changed

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SqlDependencyProcessDispatcherStorage.netfx.cs

+13-27
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,24 @@
88
using System.Diagnostics;
99
using System.Runtime.InteropServices;
1010
using System.Runtime.Versioning;
11-
using System.Threading;
1211

1312
namespace Interop.Windows.Sni
1413
{
15-
internal unsafe class SqlDependencyProcessDispatcherStorage
14+
internal class SqlDependencyProcessDispatcherStorage
1615
{
17-
private static void* s_data;
16+
private static readonly object s_lockObj = new();
17+
private static IntPtr s_data;
1818
private static int s_size;
19-
private static volatile int s_lock; // Int used for a spin-lock.
2019

2120
[ResourceExposure(ResourceScope.Process)] // SxS: there is no way to set scope = Instance, using Process which is wider
2221
[ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
2322
public static byte[] NativeGetData()
2423
{
25-
IntPtr ptr = (IntPtr)s_data;
26-
2724
byte[] result = null;
28-
if (ptr != IntPtr.Zero)
25+
if (s_data != IntPtr.Zero)
2926
{
3027
result = new byte[s_size];
31-
Marshal.Copy(ptr, result, 0, s_size);
28+
Marshal.Copy(s_data, result, 0, s_size);
3229
}
3330

3431
return result;
@@ -38,29 +35,18 @@ public static byte[] NativeGetData()
3835
[ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
3936
internal static void NativeSetData(byte[] data)
4037
{
41-
fixed (byte* pDispatcher = data)
38+
lock (s_lockObj)
4239
{
43-
while (Interlocked.CompareExchange(ref s_lock, 1, 0) != 0)
40+
if (s_data == IntPtr.Zero)
4441
{
45-
// Spin until we have the lock.
46-
Thread.Sleep(50); // Sleep with short-timeout to prevent starvation.
47-
}
48-
Trace.Assert(s_lock == 1); // Now that we have the lock, lock should be equal to 1.
49-
50-
if (s_data == null)
51-
{
52-
s_data = Marshal.AllocHGlobal(data.Length).ToPointer();
53-
54-
Trace.Assert(s_data != null);
55-
56-
Buffer.MemoryCopy(pDispatcher, s_data, data.Length, data.Length);
57-
58-
Trace.Assert(0 == s_size); // Size should still be zero at this point.
42+
s_data = Marshal.AllocHGlobal(data.Length);
43+
Trace.Assert(s_data != IntPtr.Zero);
44+
45+
Marshal.Copy(data, 0, s_data, data.Length);
46+
47+
Trace.Assert(s_size == 0); // Size should still be zero at this point
5948
s_size = data.Length;
6049
}
61-
62-
int result = Interlocked.CompareExchange(ref s_lock, 0, 1);
63-
Trace.Assert(1 == result); // The release of the lock should have been successful.
6450
}
6551
}
6652
}

0 commit comments

Comments
 (0)