Skip to content

Commit

Permalink
Release GCHandle in FSEventStreamContext release callback (dotnet#52275)
Browse files Browse the repository at this point in the history
The callbacks are sometimes delivered even after the FSEventStream is disposed
  • Loading branch information
jkotas authored May 5, 2021
1 parent b609a7d commit 1e99834
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/libraries/Common/src/Interop/OSX/Interop.EventStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ internal struct FSEventStreamContext
{
public CFIndex version;
public IntPtr info;
public IntPtr retainFunc;
public IntPtr releaseFunc;
public IntPtr retain;
public IntPtr release;
public IntPtr copyDescription;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ internal struct SCDynamicStoreContext
{
public CFIndex version;
public IntPtr info;
public IntPtr retainFunc;
public IntPtr releaseFunc;
public IntPtr retain;
public IntPtr release;
public IntPtr copyDescription;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,6 @@ private void CleanupEventStream()

StaticWatcherRunLoopManager.UnscheduleFromRunLoop(eventStream);
eventStream.Dispose();

Debug.Assert(_gcHandle.IsAllocated);
_gcHandle.Free();
}
}

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

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

// Create the event stream for the path and tell the stream to watch for file system events.
SafeEventStreamHandle eventStream = Interop.EventStream.FSEventStreamCreate(
Expand All @@ -336,7 +334,10 @@ internal unsafe void Start(CancellationToken cancellationToken)
finally
{
if (cleanupGCHandle)
{
Debug.Assert(_gcHandle.Target is RunningInstance);
_gcHandle.Free();
}
arrPaths?.Dispose();
path?.Dispose();
}
Expand Down Expand Up @@ -373,6 +374,14 @@ internal unsafe void Start(CancellationToken cancellationToken)
}
}

[UnmanagedCallersOnly]
private static void ReleaseCallback(IntPtr clientCallBackInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(clientCallBackInfo);
Debug.Assert(gcHandle.Target is RunningInstance);
gcHandle.Free();
}

[UnmanagedCallersOnly]
private static unsafe void FileSystemEventCallback(
FSEventStreamRef streamRef,
Expand Down

0 comments on commit 1e99834

Please sign in to comment.