From c4bb5b6c5eaad00a9ee7a39042c222dd1421960b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 5 May 2016 13:26:02 -0700 Subject: [PATCH] Fixing some NodeJsProjectNode refCount Issues Port of Microsoft/PTVS#1262 to try to address core memory leak issues: * Marshal incrementing refcount and not decrementing it in two places. * Automation object dispose. In my testing, this did not actually fix the problem but does fix a few real issues with the current code. --- .../SharedProject/Automation/OAProject.cs | 4 ++++ .../SharedProject/CommonProjectNode.cs | 8 +++++-- Common/Product/SharedProject/ProjectNode.cs | 22 ++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Common/Product/SharedProject/Automation/OAProject.cs b/Common/Product/SharedProject/Automation/OAProject.cs index c4bface04..45ac648dd 100644 --- a/Common/Product/SharedProject/Automation/OAProject.cs +++ b/Common/Product/SharedProject/Automation/OAProject.cs @@ -61,6 +61,10 @@ public virtual string Name { } } + public void Dispose() { + configurationManager = null; + } + /// /// Microsoft Internal Use Only. Gets the file name of the project. /// diff --git a/Common/Product/SharedProject/CommonProjectNode.cs b/Common/Product/SharedProject/CommonProjectNode.cs index 396f07c91..facb6260e 100644 --- a/Common/Product/SharedProject/CommonProjectNode.cs +++ b/Common/Product/SharedProject/CommonProjectNode.cs @@ -155,8 +155,12 @@ private IVsHierarchy InteropSafeHierarchy { if (IntPtr.Zero == unknownPtr) { return null; } - IVsHierarchy hier = Marshal.GetObjectForIUnknown(unknownPtr) as IVsHierarchy; - return hier; + try { + IVsHierarchy hier = Marshal.GetObjectForIUnknown(unknownPtr) as IVsHierarchy; + return hier; + } finally { + Marshal.Release(unknownPtr); + } } } diff --git a/Common/Product/SharedProject/ProjectNode.cs b/Common/Product/SharedProject/ProjectNode.cs index 27c7a09de..a37014a38 100644 --- a/Common/Product/SharedProject/ProjectNode.cs +++ b/Common/Product/SharedProject/ProjectNode.cs @@ -1601,6 +1601,12 @@ public override void Close() { taskProvider.Tasks.Clear(); } + var autoObject = GetAutomationObject() as Automation.OAProject; + if (autoObject != null) { + autoObject.Dispose(); + } + this.configProvider = null; + try { // Walk the tree and close all nodes. // This has to be done before the project closes, since we want @@ -2790,9 +2796,14 @@ protected internal virtual void SetCurrentConfiguration() { if (!IsProjectOpened) return; - EnvDTE.Project automationObject = GetAutomationObject() as EnvDTE.Project; + var solutionBuild = (IVsSolutionBuildManager)GetService(typeof(SVsSolutionBuildManager)); + IVsProjectCfg[] cfg = new IVsProjectCfg[1]; + ErrorHandler.ThrowOnFailure( + solutionBuild.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, GetOuterHierarchy(), cfg)); - SetConfiguration(Utilities.GetActiveConfigurationName(automationObject)); + string name; + ErrorHandler.ThrowOnFailure(cfg[0].get_CanonicalName(out name)); + SetConfiguration(name); } /// @@ -4828,7 +4839,12 @@ public virtual int InitializeForOuter(string filename, string location, string n if (canceled != 1) { // Set ourself as the project - return Marshal.QueryInterface(Marshal.GetIUnknownForObject(this), ref iid, out projectPointer); + IntPtr project = Marshal.GetIUnknownForObject(this); + try { + return Marshal.QueryInterface(project, ref iid, out projectPointer); + } finally { + Marshal.Release(project); + } } return VSConstants.OLE_E_PROMPTSAVECANCELLED;