From b7ce4c9f9dc662bfe89739d205b6e0a290fcc1da Mon Sep 17 00:00:00 2001 From: comintern Date: Sun, 4 Nov 2018 09:58:53 -0600 Subject: [PATCH] Address potential race condition and potentially un-disposed objects on TryAdd failure. --- .../WindowsApi/SubclassManager.cs | 79 +++++++++++++------ 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/Rubberduck.VBEEditor/WindowsApi/SubclassManager.cs b/Rubberduck.VBEEditor/WindowsApi/SubclassManager.cs index cd69f4ef7e..f0d6ce7bdc 100644 --- a/Rubberduck.VBEEditor/WindowsApi/SubclassManager.cs +++ b/Rubberduck.VBEEditor/WindowsApi/SubclassManager.cs @@ -37,36 +37,65 @@ public SubclassingWindow Subclass(IntPtr hwnd) return null; } - if (_subclasses.TryGetValue(hwnd, out var existing)) + lock (ThreadLock) + { + if (_subclasses.TryGetValue(hwnd, out var existing)) + { + return existing; + } + + // Any additional cases also need to be added to IsSubclassable above. + switch (windowType) + { + case WindowType.CodePane: + return TrackNewCodePane(hwnd); + case WindowType.DesignerWindow: + return TrackNewDesigner(hwnd); + default: + return null; + } + } + } + + private CodePaneSubclass TrackNewCodePane(IntPtr hwnd) + { + var codePane = new CodePaneSubclass(hwnd, null); + try { - return existing; + if (_subclasses.TryAdd(hwnd, codePane)) + { + codePane.ReleasingHandle += SubclassRemoved; + codePane.CaptionChanged += AssociateCodePane; + SubclassLogger.Trace($"Subclassed hWnd 0x{hwnd.ToInt64():X8} as CodePane."); + return codePane; + } } + catch (Exception ex) + { + SubclassLogger.Error(ex); + } + codePane.Dispose(); + return null; + } - // Any additional cases also need to be added to IsSubclassable above. - switch (windowType) + private DesignerWindowSubclass TrackNewDesigner(IntPtr hwnd) + { + var designer = new DesignerWindowSubclass(hwnd); + try + { + if (_subclasses.TryAdd(hwnd, designer)) + { + designer.ReleasingHandle += SubclassRemoved; + SubclassLogger.Trace($"Subclassed hWnd 0x{hwnd.ToInt64():X8} as DesignerWindow."); + return designer; + } + } + catch (Exception ex) { - case WindowType.CodePane: - lock (ThreadLock) - { - var codePane = new CodePaneSubclass(hwnd, null); - _subclasses.TryAdd(hwnd, codePane); - codePane.ReleasingHandle += SubclassRemoved; - codePane.CaptionChanged += AssociateCodePane; - SubclassLogger.Trace($"Subclassed hWnd 0x{hwnd.ToInt64():X8} as CodePane."); - return codePane; - } - case WindowType.DesignerWindow: - lock (ThreadLock) - { - var designer = new DesignerWindowSubclass(hwnd); - _subclasses.TryAdd(hwnd, designer); - designer.ReleasingHandle += SubclassRemoved; - SubclassLogger.Trace($"Subclassed hWnd 0x{hwnd.ToInt64():X8} as DesignerWindow."); - return designer; - } - default: - return null; + SubclassLogger.Error(ex); } + designer.Dispose(); + return null; } private void SubclassRemoved(object sender, EventArgs eventArgs)