Improve COM static store usage#5680
Merged
JohnMcPMS merged 6 commits intomicrosoft:masterfrom Aug 25, 2025
Merged
Conversation
…o static store or more issues will arise
This comment was marked as outdated.
This comment was marked as outdated.
JohnMcPMS
added a commit
to JohnMcPMS/winget-cli
that referenced
this pull request
Aug 25, 2025
The use of the COM static store was causing crashes on long lived processes because the implementation of `DllCanUnloadNow` did not count those objects, nor did it clean them up. This led to our module being unloaded, then when it was reloaded, the recreation of the static store object would invoke the deletion of the old one, which was pointing to the old, unloaded module location. WindowsPackageManager.dll serves many purposes, making the lifetime of statics complex. - It serves as "in-proc" for the CLI - It is the core implementation for the in-proc COM - It is the core implementation for the OOP COM In order to support in-proc COM, we must put static lifetime COM objects in the static store. But in order to support unloading, we must also clean them up. Additionally, we don't want to claim to be in use if the only active objects are our statics (which are typically just event handlers and their owners). We already use the WRL object count to track OOP COM server lifetime, and similarly we use it to implement `DllCanUnloadNow`. This is the count externally owned objects; those that the client has requested directly or indirectly. The major change is to remove all of our static store objects when WRL says we have no more externally owned. This is achieved by tracking the names of the objects that we insert and attempting to remove them when appropriate. The original change to use the static store was templatized and reused to hold the termination signal handler. The new test uses the CLI to validate that the implementation for `DllCanUnloadNow` (`WindowsPackageManagerInProcModuleTerminate`) detects the unload state and properly destroys the relevant objects. This is done by checking that there are internal objects allocated before the call, but none after.
JohnMcPMS
added a commit
that referenced
this pull request
Aug 25, 2025
CP from #5680 Ported changes backward from the termination handling refactor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
The use of the COM static store was causing crashes on long lived processes because the implementation of
DllCanUnloadNowdid not count those objects, nor did it clean them up. This led to our module being unloaded, then when it was reloaded, the recreation of the static store object would invoke the deletion of the old one, which was pointing to the old, unloaded module location.Design Considerations
WindowsPackageManager.dll serves many purposes, making the lifetime of statics complex.
In order to support in-proc COM, we must put static lifetime COM objects in the static store. But in order to support unloading, we must also clean them up. Additionally, we don't want to claim to be in use if the only active objects are our statics (which are typically just event handlers and their owners).
We already use the WRL object count to track OOP COM server lifetime, and similarly we use it to implement
DllCanUnloadNow. This is the count externally owned objects; those that the client has requested directly or indirectly.Change
The major change is to remove all of our static store objects when WRL says we have no more externally owned. This is achieved by tracking the names of the objects that we insert and attempting to remove them when appropriate.
The original change to use the static store was templatized and reused to hold the termination signal handler.
Validation
The new test uses the CLI to validate that the implementation for
DllCanUnloadNow(WindowsPackageManagerInProcModuleTerminate) detects the unload state and properly destroys the relevant objects. This is done by checking that there are internal objects allocated before the call, but none after.Microsoft Reviewers: Open in CodeFlow