Skip to content

Commit

Permalink
Address potential race condition and potentially un-disposed objects …
Browse files Browse the repository at this point in the history
…on TryAdd failure.
  • Loading branch information
comintern committed Nov 4, 2018
1 parent 0aaf7c1 commit b7ce4c9
Showing 1 changed file with 54 additions and 25 deletions.
79 changes: 54 additions & 25 deletions Rubberduck.VBEEditor/WindowsApi/SubclassManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit b7ce4c9

Please sign in to comment.