Skip to content

Conversation

@kring
Copy link
Member

@kring kring commented Nov 14, 2025

This PR fixes two problems with the generated code for delegates.

  1. When a native std::function is wrapped with a .NET delegate, and the delegate is invoked, that native code could end up throwing an exception. Previously, this exception would have propagated disastrously through the managed code. With this PR, it's caught at the interface layer and turned into a managed exception. Just like it would be (even before this PR) if it were a partial method implemented in native code rather than a delegate.
  2. Delegate wrappers for native functions weren't using SafeHandle to reference the native function, which meant the delegate could be garbage collected, finalized, and destroy the std::function while it was running. As described in Native callbacks can be freed while they're running #627.

Fixes #627

Sadly this does not fix all the AppDomain unload stability problems. It's still pretty easy to get a crash by entering play mode while tilesets are loading. I think I have a pretty good idea what to do next on that front, though, so I will write it up as a separate issue.

@kring kring added the reinterop Issues related to Reinterop label Nov 14, 2025
@kring kring added this to the December 2025 Release milestone Nov 14, 2025
@j9liu j9liu self-requested a review November 17, 2025 21:23
Copy link
Contributor

@j9liu j9liu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kring! Looks good to me, just two small questions.

Also, is there any particular test case I should try out that would benefit from this change?

));

// A a C# delegate type that wraps a std::function, and arrange for
// A C# delegate type that wraps a std::function, and arrange for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo?

Suggested change
// A C# delegate type that wraps a std::function, and arrange for
// A C# delegate type that wraps a std::function, and arranges for

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth noting this change in CHANGES.md?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reinterop Issues related to Reinterop

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Native callbacks can be freed while they're running

3 participants