From 18f6524b63123ade916831bdd9f2b7b3d7016957 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Wed, 22 Jan 2020 12:34:47 +0000 Subject: [Debugger] Provide project to DebuggerSession mapping The DebuggerService now has two methods that can map from an IRunTarget to a DebuggerSession or the other way around. The ExecutionCommand now has an IRunTarget property which is used by the DebuggerService to create this mapping from DebuggerSession to IRunTarget. IRunTarget is implemented by SolutionItem. Fixes VSTS #1012614 - Improvements to DebuggerSession for XAML Hot Reload --- .../MonoDevelop.Debugger/DebuggingService.cs | 22 ++++++++++++++++++++++ .../MonoDevelop.Core.Execution/ExecutionCommand.cs | 8 +++++++- .../MonoDevelop.Projects/DotNetProject.cs | 5 ++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs index 8fb53e652f..60d5fa309f 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs @@ -149,6 +149,26 @@ namespace MonoDevelop.Debugger return sessions.Keys.ToArray (); } + public static DebuggerSession GetSession (IRunTarget runTarget) + { + foreach (KeyValuePair item in sessions.ToArray ()) { + if (item.Value.RunTarget == runTarget) { + return item.Key; + } + } + return null; + } + + public static IRunTarget GetRunTarget (DebuggerSession session) + { + foreach (KeyValuePair item in sessions.ToArray ()) { + if (item.Key == session) { + return item.Value.RunTarget; + } + } + return null; + } + public static ProcessInfo [] GetProcesses () { return sessions.Keys.Where (s => !s.IsRunning).SelectMany (s => s.GetProcesses ()).ToArray (); @@ -721,6 +741,7 @@ namespace MonoDevelop.Debugger sessionManager = new SessionManager (session, IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (System.IO.Path.GetFileNameWithoutExtension (startInfo.Command)).Console, factory, timer); else sessionManager = new SessionManager (session, c, factory, timer); + sessionManager.RunTarget = cmd.RunTarget; SetupSession (sessionManager); SetDebugLayout (); @@ -757,6 +778,7 @@ namespace MonoDevelop.Debugger public readonly DebuggerSession Session; public readonly DebugAsyncOperation debugOperation; public readonly DebuggerEngine Engine; + internal IRunTarget RunTarget { get; set; } internal ITimeTracker StartTimer { get; set; } internal bool TrackActionTelemetry { get; set; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionCommand.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionCommand.cs index 3db966161d..93fb1343d4 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionCommand.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionCommand.cs @@ -24,7 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; +using MonoDevelop.Projects; namespace MonoDevelop.Core.Execution { @@ -46,5 +46,11 @@ namespace MonoDevelop.Core.Execution /// Execution target. For example, a specific device. /// public ExecutionTarget Target { get; set; } + + /// + /// IRunTarget item associated with this execution command. This allows the DebuggerSession to be + /// associated with an IRunTarget (typically a Project). + /// + public IRunTarget RunTarget { get; set; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs index 8712a31c23..8c826d0fb2 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs @@ -1505,7 +1505,10 @@ namespace MonoDevelop.Projects public ExecutionCommand CreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration, ProjectRunConfiguration runConfiguration) { - return ProjectExtension.OnCreateExecutionCommand (configSel, configuration, runConfiguration); + var command = ProjectExtension.OnCreateExecutionCommand (configSel, configuration, runConfiguration); + if (command != null) + command.RunTarget ??= this; + return command; } internal protected virtual ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) -- cgit v1.2.3 From 322e35b5312260d2cf8cd50e1d01531660a07e5a Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Wed, 22 Jan 2020 17:02:53 +0000 Subject: [Debugger] Make DebuggingService dictionaries thread safe. The sessions dictionary and the nextStatementLocations dictionary were accessed from multiple threads. Changed these dictionaries to be ConcurrentDictionary so their use is thread safe. --- .../MonoDevelop.Debugger/DebuggingService.cs | 28 ++++++++++------------ 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs index 60d5fa309f..25c19d22ad 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs @@ -67,8 +67,8 @@ namespace MonoDevelop.Debugger static readonly BreakpointStore breakpoints = new BreakpointStore (); static readonly DebugExecutionHandlerFactory executionHandlerFactory; - static Dictionary nextStatementLocations = new Dictionary (); - static Dictionary sessions = new Dictionary (); + static ConcurrentDictionary nextStatementLocations = new ConcurrentDictionary (); + static ConcurrentDictionary sessions = new ConcurrentDictionary (); static Backtrace currentBacktrace; static SessionManager currentSession; static int currentFrame; @@ -151,7 +151,7 @@ namespace MonoDevelop.Debugger public static DebuggerSession GetSession (IRunTarget runTarget) { - foreach (KeyValuePair item in sessions.ToArray ()) { + foreach (KeyValuePair item in sessions) { if (item.Value.RunTarget == runTarget) { return item.Key; } @@ -161,10 +161,8 @@ namespace MonoDevelop.Debugger public static IRunTarget GetRunTarget (DebuggerSession session) { - foreach (KeyValuePair item in sessions.ToArray ()) { - if (item.Key == session) { - return item.Value.RunTarget; - } + if (sessions.TryGetValue (session, out SessionManager sessionManager)) { + return sessionManager.RunTarget; } return null; } @@ -177,8 +175,8 @@ namespace MonoDevelop.Debugger public static BreakEventStatus GetBreakpointStatus (Breakpoint bp) { var result = BreakEventStatus.Disconnected; - foreach (var sesion in sessions.Keys.ToArray ()) { - var status = bp.GetStatus (sesion); + foreach (var session in sessions.Keys) { + var status = bp.GetStatus (session); if (status == BreakEventStatus.Bound) return BreakEventStatus.Bound; else @@ -418,7 +416,7 @@ namespace MonoDevelop.Debugger static void SetupSession (SessionManager sessionManager) { - sessions.Add (sessionManager.Session, sessionManager); + sessions [sessionManager.Session] = sessionManager; isBusy = false; var session = sessionManager.Session; session.Breakpoints = breakpoints; @@ -463,7 +461,7 @@ namespace MonoDevelop.Debugger currentBacktrace = null; } busyStatusIcon = null; - sessions.Remove (sessionManager.Session); + sessions.TryRemove (sessionManager.Session, out _); pinnedWatches.InvalidateAll (); } @@ -549,7 +547,7 @@ namespace MonoDevelop.Debugger public static void Pause () { - foreach (var session in sessions.Keys.ToArray ()) { + foreach (var session in sessions.Keys) { if (session.IsRunning) session.Stop (); } @@ -577,7 +575,7 @@ namespace MonoDevelop.Debugger if (HandleStopQueue ()) return; - foreach (var session in sessions.Keys.ToArray ()) { + foreach (var session in sessions.Keys) { if (!session.IsRunning) session.Continue (); } @@ -695,7 +693,7 @@ namespace MonoDevelop.Debugger PropertyService.Set ("Monodevelop.StackTrace.ShowLineNumber", options.EvaluationOptions.StackFrameFormat.Line); PropertyService.Set ("Monodevelop.StackTrace.ShowExternalCode", options.EvaluationOptions.StackFrameFormat.ExternalCode); - foreach (var session in sessions.Keys.ToArray ()) { + foreach (var session in sessions.Keys) { session.Options.EvaluationOptions = GetUserOptions ().EvaluationOptions; } if (EvaluationOptionsChanged != null) @@ -1133,7 +1131,7 @@ namespace MonoDevelop.Debugger if (!IsDebugging) return; - foreach (var pair in sessions.ToArray ()) { + foreach (var pair in sessions) { pair.Key.Exit (); Cleanup (pair.Value); } -- cgit v1.2.3