From 89c64e389c7c14dfcc83822c76be7b28fa58baa8 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 12 Jul 2009 12:20:25 +0000 Subject: [PATCH] Fixed thread-safety problem in DefaultReturnType. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4432 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Implementations/DefaultReturnType.cs | 102 ++++++++++-------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs index 9fe6cb188b..e9c8442a79 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs @@ -67,26 +67,33 @@ namespace ICSharpCode.SharpDevelop.Dom return c; } - bool getMembersBusy; + // Required to prevent stack overflow when calling GetMethods() on a class with cyclic inheritance + // replaces old 'getMembersBusy' flag which wasn't thread-safe + [ThreadStatic] static BusyManager _busyManager; + + static BusyManager busyManager { + get { return _busyManager ?? (_busyManager = new BusyManager()); } + } public override List GetMethods() { - if (getMembersBusy) return new List(); - getMembersBusy = true; List l = new List(); - l.AddRange(c.Methods); - if (c.ClassType == ClassType.Interface) { - if (c.BaseTypes.Count == 0) { - AddMethodsFromBaseType(l, c.ProjectContent.SystemTypes.Object); - } else { - foreach (IReturnType baseType in c.BaseTypes) { - AddMethodsFromBaseType(l, baseType); + using (var busyLock = busyManager.Enter(this)) { + if (busyLock.Success) { + l.AddRange(c.Methods); + if (c.ClassType == ClassType.Interface) { + if (c.BaseTypes.Count == 0) { + AddMethodsFromBaseType(l, c.ProjectContent.SystemTypes.Object); + } else { + foreach (IReturnType baseType in c.BaseTypes) { + AddMethodsFromBaseType(l, baseType); + } + } + } else { + AddMethodsFromBaseType(l, c.BaseType); } } - } else { - AddMethodsFromBaseType(l, c.BaseType); } - getMembersBusy = false; return l; } @@ -120,18 +127,19 @@ namespace ICSharpCode.SharpDevelop.Dom public override List GetProperties() { - if (getMembersBusy) return new List(); - getMembersBusy = true; List l = new List(); - l.AddRange(c.Properties); - if (c.ClassType == ClassType.Interface) { - foreach (IReturnType baseType in c.BaseTypes) { - AddPropertiesFromBaseType(l, baseType); + using (var busyLock = busyManager.Enter(this)) { + if (busyLock.Success) { + l.AddRange(c.Properties); + if (c.ClassType == ClassType.Interface) { + foreach (IReturnType baseType in c.BaseTypes) { + AddPropertiesFromBaseType(l, baseType); + } + } else { + AddPropertiesFromBaseType(l, c.BaseType); + } } - } else { - AddPropertiesFromBaseType(l, c.BaseType); } - getMembersBusy = false; return l; } @@ -162,41 +170,43 @@ namespace ICSharpCode.SharpDevelop.Dom public override List GetFields() { - if (getMembersBusy) return new List(); - getMembersBusy = true; List l = new List(); - l.AddRange(c.Fields); - if (c.ClassType == ClassType.Interface) { - foreach (IReturnType baseType in c.BaseTypes) { - l.AddRange(baseType.GetFields()); - } - } else { - IReturnType baseType = c.BaseType; - if (baseType != null) { - l.AddRange(baseType.GetFields()); + using (var busyLock = busyManager.Enter(this)) { + if (busyLock.Success) { + l.AddRange(c.Fields); + if (c.ClassType == ClassType.Interface) { + foreach (IReturnType baseType in c.BaseTypes) { + l.AddRange(baseType.GetFields()); + } + } else { + IReturnType baseType = c.BaseType; + if (baseType != null) { + l.AddRange(baseType.GetFields()); + } + } } } - getMembersBusy = false; return l; } public override List GetEvents() { - if (getMembersBusy) return new List(); - getMembersBusy = true; List l = new List(); - l.AddRange(c.Events); - if (c.ClassType == ClassType.Interface) { - foreach (IReturnType baseType in c.BaseTypes) { - l.AddRange(baseType.GetEvents()); - } - } else { - IReturnType baseType = c.BaseType; - if (baseType != null) { - l.AddRange(baseType.GetEvents()); + using (var busyLock = busyManager.Enter(this)) { + if (busyLock.Success) { + l.AddRange(c.Events); + if (c.ClassType == ClassType.Interface) { + foreach (IReturnType baseType in c.BaseTypes) { + l.AddRange(baseType.GetEvents()); + } + } else { + IReturnType baseType = c.BaseType; + if (baseType != null) { + l.AddRange(baseType.GetEvents()); + } + } } } - getMembersBusy = false; return l; }