Skip to content

Commit 5980ac2

Browse files
committed
Release GCHandle in FSEventStreamContext release callback
The callbacks are sometimes delivered even after the FSEventStream is disposed
1 parent 89a816f commit 5980ac2

File tree

3 files changed

+16
-7
lines changed

3 files changed

+16
-7
lines changed

src/libraries/Common/src/Interop/OSX/Interop.EventStream.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ internal struct FSEventStreamContext
7878
{
7979
public CFIndex version;
8080
public IntPtr info;
81-
public IntPtr retainFunc;
82-
public IntPtr releaseFunc;
81+
public IntPtr retain;
82+
public IntPtr release;
8383
public IntPtr copyDescription;
8484
}
8585

src/libraries/Common/src/Interop/OSX/Interop.SystemConfiguration.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ internal struct SCDynamicStoreContext
1919
{
2020
public CFIndex version;
2121
public IntPtr info;
22-
public IntPtr retainFunc;
23-
public IntPtr releaseFunc;
22+
public IntPtr retain;
23+
public IntPtr release;
2424
public IntPtr copyDescription;
2525
}
2626

src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,6 @@ private void CleanupEventStream()
275275

276276
StaticWatcherRunLoopManager.UnscheduleFromRunLoop(eventStream);
277277
eventStream.Dispose();
278-
279-
Debug.Assert(_gcHandle.IsAllocated);
280-
_gcHandle.Free();
281278
}
282279
}
283280

@@ -314,6 +311,7 @@ internal unsafe void Start(CancellationToken cancellationToken)
314311

315312
Interop.EventStream.FSEventStreamContext context = default;
316313
context.info = GCHandle.ToIntPtr(_gcHandle);
314+
context.release = (IntPtr)(delegate* unmanaged<IntPtr, void>)&ReleaseCallback;
317315

318316
// Create the event stream for the path and tell the stream to watch for file system events.
319317
SafeEventStreamHandle eventStream = Interop.EventStream.FSEventStreamCreate(
@@ -336,7 +334,10 @@ internal unsafe void Start(CancellationToken cancellationToken)
336334
finally
337335
{
338336
if (cleanupGCHandle)
337+
{
338+
Debug.Assert(_gcHandle.Target is RunningInstance);
339339
_gcHandle.Free();
340+
}
340341
arrPaths?.Dispose();
341342
path?.Dispose();
342343
}
@@ -373,6 +374,14 @@ internal unsafe void Start(CancellationToken cancellationToken)
373374
}
374375
}
375376

377+
[UnmanagedCallersOnly]
378+
private static void ReleaseCallback(IntPtr clientCallBackInfo)
379+
{
380+
GCHandle gcHandle = GCHandle.FromIntPtr(clientCallBackInfo);
381+
Debug.Assert(gcHandle.Target is RunningInstance);
382+
gcHandle.Free();
383+
}
384+
376385
[UnmanagedCallersOnly]
377386
private static unsafe void FileSystemEventCallback(
378387
FSEventStreamRef streamRef,

0 commit comments

Comments
 (0)