[squeak-dev] Tackling Context>>#runUntilErrorReturnFrom: (was: BUG/REGRESSION while debugging Generator >> #nextPut:)

Thiede, Christoph Christoph.Thiede at student.hpi.uni-potsdam.de
Mon Mar 8 19:24:24 UTC 2021


The formatting of this message was unacceptable. I'm attaching it in a reformated style ...

Best,
Christoph

________________________________
Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im Auftrag von Thiede, Christoph
Gesendet: Montag, 8. März 2021 20:21 Uhr
An: squeak-dev at lists.squeakfoundation.org
Betreff: [squeak-dev] Tackling Context>>#runUntilErrorReturnFrom: (was: BUG/REGRESSION while debugging Generator >> #nextPut:)

Hi all, hi Eliot, hi Marcel,

it's been a long time, but this issue still exists and I have been making a lot of thoughts about it while investigating this and other issues. Marcel and I will soon release a fix for the infinite debugger chains in general, but this issue is a separate one.

<short recap>
Under certain circumstances, running a single step in a debugger (mostly via the Over button) abandons the current UI process and proceeds the debugged process in its place. This is caused by an insane and extremely powerful hack in Context>>#runUntilErrorReturnFrom:, which hacks the context to be simulated into the currently running process. This can speed up debugging by around factor 1000. To ensure that the execution returns to the debugging process, two guard contexts are installed on top of the respective context.
Unfortunately, if the debugged process contains any piece of context metaprogramming, i.e. by implementing coroutine logic with Context>>#swapSender:, or by performing #jumps, this can uninstall the guard contexts or make them unreachable, eventually causing the debugged process to successfully hijack the debugging process and never return control back to it.
</short recap>

After all, I think there is no viable alternative to explicitly informing the debugger about such acts of context metaprogramming. For this reason, I have set up a working and unpolished prototype in my image, which, in a nutshell, applies the following changes to Context:

1. In #jump and #swapSender:, insert a send {self informDebuggerAboutContextSwitchTo: coroutine} right before installing the new sender.
2. #informDebuggerAboutContextSwitchTo: searches the sender stack for an UnhandledError handler that was installed by #runUntilErrorOrReturnFrom:. If it finds one, it checks whether this context would still be available after the context switch. (If yes, nothing is done, otherwise stepping over complex messages such as {self systemNavigation allCallsOn: #foo} would become really messy.) If no, an UnhandledError is signaled to abort the #runUntilErrorOrReturnFrom: execution prematurely.

You can find the details in the attached changeset, but IMO implementation details are less relevant for the current discussion than a general understanding of the problem and the solution approach. Here are some questions for you:

1. Would you agree that is the right approach to the problem because there are no alternatives?

2. Now it's getting indeed a bit more technical: At the moment, #findNextRunUntilErrorOrReturnFromCalleeContextUpTo: in my implementation (horrible name, I know ...) manually traverses the chain of #nextHandlerContexts to search for an UnhandledError handler of interest. However, I don't really like this approach because a) it creates a high coupling to the #runUntilErrorOrReturnFrom: implementation (well, on the other hand, both methods resist in the same class ...) and b) it might introduce a noticeable performance drop (premature benchmarks have suggested an overhead of 5%-25% depending on the task).
I need to build better measures, but a question in general: Are we willing to accept this performance drop in order to regain correctness? (In my opinion, we should be willing, it is only used for debugging and "still fast enough for our neurons" :-))
An alternative to manually scanning all handler contexts could be to introduce a new exception for this (maybe ContextSwitchNotification) and let the VM do all the work. Or am I overrating "The Great VM" in this regard and things won't be able to become faster than #handleSignal: at all? For such a low-level, performance-critical decision, I think design questions should be secondary. Do you have some thoughts and opinions about this

I am looking forward to your feedback! Let's get this problem solved, too, definitively before the next release! :-)

Best, Christoph

runUntilErrorOrReturnFrom.cs<http://forum.world.st/file/t372205/runUntilErrorOrReturnFrom.cs>
Carpe Squeak!

________________________________
Sent from the Squeak - Dev mailing list archive<http://forum.world.st/Squeak-Dev-f45488.html> at Nabble.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20210308/b3a9fffd/attachment.html>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: runUntilErrorOrReturnFrom.4.cs
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20210308/b3a9fffd/attachment.ksh>


More information about the Squeak-dev mailing list