Hi all, here is your almost-weekly debugger-related bug report :D
Steps to reproduce:
- Debug it:
self inform: #foo.
- Press over.
- In the dialog window, press dialog invocation.
- A second debugger on the same process opens. Press debug and select any context below #inform:.
Let's fork this guide into two branches:
A.5 In the dialog window, press OK.
A.6 In the second debugger, press Over.
B.5 In the second debugger, press Over.
(well, maybe I should have refactored both branches a bit ;))
Expected behavior (branch-invariant):
The dialog window closes.
The process runs until the #inform: context is reached and then suspends.
Afterward, you can continue debugging the process in the second debugger.
The first debugger does not change at all.
Actual behavior:
A: Error from second debugger: aContext not in process chain!
Reason:
In step 5, the process has run until the #DoIt context was reached, as instructed by the first debugger.
In step 6, the second debugger tries to resume a dead context.
B: Error in first debugger shown (in the debugged process): UndefinedObject does not
respond to #findContextSuchThat:.
Reason: suspendendedContext of the process is nil while stepping via the second debugger.
Some thoughts:
Using any of the debuggers will bring the other one out of sync. After step 4, you are very likely to get at least one debugger error when you do some steps
in both debuggers.
Once, I also managed to generate just another infinite debugger chain ...
This situation occurs because #debugInvocation calls Processor>>#debug:title: directly. Usually, an UnhandledError will be raised by a halt and caught
by the first open debugger in #runUntilErrorOrReturnFrom:. This is not the case here.
Questions:
What is the actual defect?
Should we avoid opening a second debugger in #debugInvocation? Actually, I would like to keep this second debugger, as you don't lose the context from the first debugger.
A very primitive solution could be to replace the current implementation by a halt. Unfortunately, this gives you all the irrelevant stack noise above the invocation context (#findInvocationContext), added to the disadvantage mentioned before ...
One possible solution approach for A:
Should we maybe implement some kind of synchronization between multiple debuggers on the same process? An approach might be to use the observer pattern and register dependent debuggers in #informExistingDebugger:label:
(and deregister them in #release, of course). Each step action in one debugger then could post-notify the other debugger, which could check if the current context is dead and, if it is, peel its context back to the next alive context.
How would you think about this? :)
I would be very happy to hear your knowledge & thoughts about both issues! :-)
Best,
Christoph