Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: Remove exception handler for pagemap on unloading #746

Merged
merged 2 commits into from
Feb 12, 2025

Conversation

NeilMonday
Copy link
Contributor

@NeilMonday NeilMonday commented Feb 11, 2025

When using snmalloc in a DLL, the exception handler is not removed when the DLL is unloaded. This will cause a crash if the EXE later throws an exception.

Example:

  1. An EXE loads a DLL which uses snmalloc
  2. AddVectoredExceptionHandler gets called to add HandleReadonlyLazyCommit as an exception handler
  3. The EXE unloads the DLL (the memory at the address where the function HandleReadonlyLazyCommit existed has been freed)
  4. The EXE throws an exception, and is expecting its own exception handler to handle it
  5. While throwing the EXE's exception, MSVC tries to call HandleReadonlyLazyCommit and hits an access violation since that no longer exists

To resolve this, I'm adding code to call RemoveVectoredExceptionHandler when the Singleton is destroyed. That way MSVC won't have a dangling function pointer after the DLL is unloaded.

Note: This adds an extra template param to Singleton class, which probably will affect other platforms, which I have not updated.

Comment on lines 110 to 114
if (!g_Handler)
{
g_Handler = AddVectoredExceptionHandler(1, HandleReadonlyLazyCommit);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

How about something like this:

Suggested change
if (!g_Handler)
{
g_Handler = AddVectoredExceptionHandler(1, HandleReadonlyLazyCommit);
}
}
// Keep a handle for the exception handler, so we can remove it later
// when needed.
static PVOID g_Handler{};
// Destructor for removing exception handler.
static OnDestruct tidy([](){
if (g_Handler)
{
RemoveVectoredExceptionHandler(g_Handler);
g_Handler = NULL; // Prevent dangling pointer
}
});
// Add exception handler for lazy commit.
if (!g_Handler)
{
g_Handler = AddVectoredExceptionHandler(1, HandleReadonlyLazyCommit);
}
}

It wouldn't need the Singleton to change, and I believe should get called in the right place to remove the exception handler?

Copy link
Member

Choose a reason for hiding this comment

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

This is using the

/**
* Helper class to execute a specified function on destruction.
*/
template<typename F>
class OnDestruct
{
F f;
public:
OnDestruct(F f) : f(f) {}
~OnDestruct()
{
f();
}
};

which is how I typically get things to get destructed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That seems like it was made exactly for this situation 👍

I'll just try it out today and update the PR.

Copy link
Member

@mjp41 mjp41 left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for addressing the feedback. This is not currently tested by CI. Can you confirm that it addresses your issue, then I can merge.

@NeilMonday
Copy link
Contributor Author

LGTM, thanks for addressing the feedback. This is not currently tested by CI. Can you confirm that it addresses your issue, then I can merge.

Everything looks good on my end. It is now able to remove the exception handler. Thanks.

@mjp41 mjp41 changed the title Adding a function to deinitialise the singleton so we can remove our exception handler. Windows: Remove exception handler for pagemap on unloading Feb 12, 2025
@mjp41 mjp41 merged commit ef47482 into microsoft:main Feb 12, 2025
66 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants