Browse Source

enforce all DoEvents from pads on the main thread to avoid race conditions in debugger. Do delayed invalidate on all pads.

pull/18/head
Siegfried Pammer 14 years ago
parent
commit
77cb734df9
  1. 35
      src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs
  2. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs
  3. 2
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs
  4. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
  5. 23
      src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs
  6. 4
      src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs
  7. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
  8. 2
      src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs
  9. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
  10. 16
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
  11. 2
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs
  12. 10
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs
  13. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
  14. 3
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/Utils.cs

35
src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -40,7 +40,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods;
extMethodsItem.Click += delegate {
extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods = !DebuggingOptions.Instance.ShowExternalMethods;
RefreshPad();
CallStackPad.InvalidateCallstackPad();
};
MenuItem moduleItem = new MenuItem();
@ -49,7 +49,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -49,7 +49,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
moduleItem.Click += delegate {
moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames = !DebuggingOptions.Instance.ShowModuleNames;
((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d;
RefreshPad();
CallStackPad.InvalidateCallstackPad();
};
MenuItem argNamesItem = new MenuItem();
@ -57,7 +57,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -57,7 +57,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames;
argNamesItem.Click += delegate {
argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames = !DebuggingOptions.Instance.ShowArgumentNames;
RefreshPad();
CallStackPad.InvalidateCallstackPad();
};
MenuItem argValuesItem = new MenuItem();
@ -65,7 +65,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -65,7 +65,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues;
argValuesItem.Click += delegate {
argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues = !DebuggingOptions.Instance.ShowArgumentValues;
RefreshPad();
CallStackPad.InvalidateCallstackPad();
};
MenuItem lineItem = new MenuItem();
@ -74,7 +74,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -74,7 +74,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
lineItem.Click += delegate {
lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers = !DebuggingOptions.Instance.ShowLineNumbers;
((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d;
RefreshPad();
CallStackPad.InvalidateCallstackPad();
};
return new ContextMenu() {
@ -98,12 +98,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -98,12 +98,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (debuggedProcess != null) {
debuggedProcess.Paused += debuggedProcess_Paused;
}
RefreshPad();
CallStackPad.InvalidateCallstackPad();
}
void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
CallStackPad.InvalidateCallstackPad();
}
void View_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
@ -140,7 +140,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -140,7 +140,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
}
public void RefreshPad()
internal void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) {
view.ItemsSource = null;
@ -278,6 +278,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -278,6 +278,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
CallStackPadContent callStackList;
static CallStackPad instance;
public static CallStackPad Instance {
get { return instance; }
}
public CallStackPad()
{
instance = this;
}
public override object Control {
get {
return callStackList;
@ -294,9 +305,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -294,9 +305,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
callStackList.SelectProcess(process);
}
public override void RefreshPad()
protected override void RefreshPad()
{
callStackList.RefreshPad();
}
public static void InvalidateCallstackPad()
{
if (instance != null)
instance.InvalidatePad();
}
}
}

6
src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs

@ -49,7 +49,7 @@ namespace Debugger.AddIn @@ -49,7 +49,7 @@ namespace Debugger.AddIn
list.WatchItems.Add(text);
}
pad.RefreshPad();
pad.InvalidatePad();
}
}
}
@ -67,7 +67,7 @@ namespace Debugger.AddIn @@ -67,7 +67,7 @@ namespace Debugger.AddIn
return;
list.WatchItems.Remove(node);
((WatchPad)this.Owner).RefreshPad();
((WatchPad)this.Owner).InvalidatePad();
}
}
}
@ -77,7 +77,7 @@ namespace Debugger.AddIn @@ -77,7 +77,7 @@ namespace Debugger.AddIn
public override void Run()
{
if (this.Owner is WatchPad) {
((WatchPad)this.Owner).RefreshPad();
((WatchPad)this.Owner).InvalidatePad();
}
}
}

2
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs

@ -74,7 +74,7 @@ namespace Debugger.AddIn.Pads.Controls @@ -74,7 +74,7 @@ namespace Debugger.AddIn.Pads.Controls
if (!WatchPad.Instance.WatchList.WatchItems.Any(n => text.FullName == ((TreeNodeWrapper)n).Node.FullName))
WatchPad.Instance.WatchList.WatchItems.Add(node);
WatchPad.Instance.RefreshPad();
WatchPad.Instance.InvalidatePad();
}
}
}

6
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs

@ -60,8 +60,8 @@ namespace Debugger.AddIn.Pads.Controls @@ -60,8 +60,8 @@ namespace Debugger.AddIn.Pads.Controls
}
if (e.Key == Key.Enter || e.Key == Key.Escape) {
myList.UnselectAll();
LocalVarPad.Instance.RefreshPad();
WatchPad.Instance.RefreshPad();
LocalVarPad.Instance.InvalidatePad();
WatchPad.Instance.InvalidatePad();
}
}
@ -75,7 +75,7 @@ namespace Debugger.AddIn.Pads.Controls @@ -75,7 +75,7 @@ namespace Debugger.AddIn.Pads.Controls
SelectedNode.Node.Name = cell.CommandText;
myList.UnselectAll();
if (WatchType == WatchListType.Watch) {
WatchPad.Instance.RefreshPad();
WatchPad.Instance.InvalidatePad();
}
SelectedNode.IsEditing = false;
}

23
src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -28,7 +28,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (this.toolbar != null) {
this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top);
this.panel.Children.Add(toolbar);
}
@ -53,8 +53,27 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -53,8 +53,27 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
public virtual void RefreshPad()
/// <summary>
/// Never call this directly. Always use InvalidatePad()
/// </summary>
protected virtual void RefreshPad()
{
}
bool invalidatePadEnqueued;
public void InvalidatePad()
{
WorkbenchSingleton.AssertMainThread();
if (invalidatePadEnqueued || WorkbenchSingleton.Workbench == null)
return;
invalidatePadEnqueued = true;
WorkbenchSingleton.SafeThreadAsyncCall(
delegate {
invalidatePadEnqueued = false;
RefreshPad();
});
}

4
src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs

@ -51,7 +51,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -51,7 +51,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
debuggedProcess.Modules.Added += debuggedProcess_ModuleLoaded;
debuggedProcess.Modules.Removed += debuggedProcess_ModuleUnloaded;
}
RefreshPad();
InvalidatePad();
}
void debuggedProcess_ModuleLoaded(object sender, CollectionItemEventArgs<Module> e)
@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
RemoveModule(e.Item);
}
public override void RefreshPad()
protected override void RefreshPad()
{
loadedModulesList.ItemCollection.Clear();
if (debuggedProcess != null) {

6
src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs

@ -46,15 +46,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -46,15 +46,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (debuggedProcess != null) {
debuggedProcess.Paused += debuggedProcess_Paused;
}
RefreshPad();
InvalidatePad();
}
void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
InvalidatePad();
}
public override void RefreshPad()
protected override void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning) {
localVarList.WatchItems.Clear();

2
src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs

@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
this.console = new ConsoleControl();
this.panel.Children.Add(console);
this.console.Encoding = Encoding.Default;
RefreshPad();
RefreshPad(); // exception
this.console.SetReadonly();
DebuggerService.DebugStopped += DebuggerService_DebugStopped;

6
src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -37,7 +37,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
public override void RefreshPad()
protected override void RefreshPad()
{
// BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh)
// REQUEST: need to refresh when pad becomes visible -> VisibleChanged event?
@ -61,12 +61,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -61,12 +61,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (debuggedProcess != null) {
debuggedProcess.Paused += debuggedProcess_Paused;
}
RefreshPad();
InvalidatePad();
}
void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
InvalidatePad();
}
}
}

16
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs

@ -62,10 +62,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -62,10 +62,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
DebuggerService.DebugStarted += OnReset;
DebuggerService.DebugStopped += OnReset;
RefreshPad();
InvalidatePad();
}
public override void RefreshPad()
protected override void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning) {
return;
@ -79,9 +79,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -79,9 +79,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
try {
// create all simple ThreadStacks
foreach (Thread thread in debuggedProcess.Threads) {
if (debuggedProcess.IsPaused) {
Utils.DoEvents(debuggedProcess);
}
Utils.DoEvents(debuggedProcess);
CreateThreadStack(thread);
}
}
@ -136,7 +134,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -136,7 +134,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
get { return parallelStacksView; }
set {
parallelStacksView = value;
RefreshPad();
InvalidatePad();
}
}
@ -144,7 +142,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -144,7 +142,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
get { return isMethodView; }
set {
isMethodView = value;
RefreshPad();
InvalidatePad();
}
}
@ -168,7 +166,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -168,7 +166,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
private void OnProcessPaused(object sender, ProcessEventArgs e)
{
RefreshPad();
InvalidatePad();
}
private void AddChildren(ThreadStack parent)
@ -588,7 +586,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -588,7 +586,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ToggleSelectedFrameBookmark(e.Location);
if (isMethodView)
RefreshPad();
InvalidatePad();
}
#endregion

2
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs

@ -53,7 +53,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -53,7 +53,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
foreach(dynamic current in items) {
(current.Tag as Thread).Suspended = !suspended;
}
RefreshPad();
InvalidatePad();
};
menu.Items.Add(freezeItem);

10
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs

@ -65,12 +65,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -65,12 +65,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
debuggedProcess.Threads.Added += debuggedProcess_ThreadStarted;
}
runningThreadsList.ItemCollection.Clear();
RefreshPad();
InvalidatePad();
}
void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
InvalidatePad();
}
void debuggedProcess_ThreadStarted(object sender, CollectionItemEventArgs<Thread> e)
@ -78,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -78,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
AddThread(e.Item);
}
public override void RefreshPad()
protected override void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning) {
runningThreadsList.ItemCollection.Clear();
@ -88,9 +88,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -88,9 +88,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
using(new PrintTimes("Threads refresh")) {
try {
foreach (Thread t in debuggedProcess.Threads) {
if (debuggedProcess.IsPaused) {
Utils.DoEvents(debuggedProcess);
}
Utils.DoEvents(debuggedProcess);
AddThread(t);
}
} catch(AbortedBecauseDebuggeeResumedException) {

6
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs

@ -181,15 +181,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -181,15 +181,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
debuggedProcess.Paused += debuggedProcess_Paused;
debuggedProcess.Exited += ResetPad;
}
RefreshPad();
InvalidatePad();
}
void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
InvalidatePad();
}
public override void RefreshPad()
protected override void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning)
return;

3
src/AddIns/Debugger/Debugger.AddIn/TreeModel/Utils.cs

@ -10,6 +10,7 @@ using System.Windows.Threading; @@ -10,6 +10,7 @@ using System.Windows.Threading;
using Debugger.AddIn.Pads.Controls;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn.TreeModel
@ -19,6 +20,7 @@ namespace Debugger.AddIn.TreeModel @@ -19,6 +20,7 @@ namespace Debugger.AddIn.TreeModel
/// <param name="process">Process on which to track debuggee state</param>
public static void DoEvents(Process process)
{
WorkbenchSingleton.AssertMainThread();
if (process == null) return;
DebuggeeState oldState = process.DebuggeeState;
WpfDoEvents();
@ -31,6 +33,7 @@ namespace Debugger.AddIn.TreeModel @@ -31,6 +33,7 @@ namespace Debugger.AddIn.TreeModel
public static void WpfDoEvents()
{
WorkbenchSingleton.AssertMainThread();
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => frame.Continue = false));
Dispatcher.PushFrame(frame);

Loading…
Cancel
Save