[squeak-dev] Error: infinite recursion in doesNotUnderstand:
mail at jaromir.net
mail at jaromir.net
Tue Jan 11 21:07:36 UTC 2022
Hi Christoph,
> On 2022-01-10T12:29:26+00:00, christoph.thiede at student.hpi.uni-potsdam.de wrote:
> If I just evaluate "nil foo" and press Proceed two consecutive times, I get this "infinite recursion" error and my iterative development cycle is broken. :-( Can we fix this?
> I would really appreciate it if we could keep the existing workflows intact.
I've been thinking about the idea of "restricting" the MNU 'infinite recursion' fix; from my perspective the minimum new #terminate needs is to prevent the infinite MNU loop *during termination*, which would keep your workflow intact and the new #terminate resilient; here's a suggestion:
doesNotUnderstand: aMessage
| exception resumeValue |
(exception := MessageNotUnderstood new)
message: aMessage;
receiver: self.
resumeValue := exception signal.
^exception reachedDefaultHandler "i.e. exception was not caught..."
ifTrue:
[[aMessage sentTo: self]
on: MessageNotUnderstood
do: [:ex | thisContext isTerminating ifFalse: [ex pass]]] "<------------------ here's the needed minimum"
ifFalse: [resumeValue]
where #isTerminating checks the context stack's bottom context for a mark left by #terminate, and reads:
isTerminating
"Answer true if the receiver's stack is being unwound by #terminate."
| bottom |
bottom := self bottomContext.
^bottom stackPtr > 0 and: [(bottom at: bottom stackPtr) = #unwindingInTerminate]
For this to work I'd only sneak the following line at the beginning of #terminate: to mark the receiver's stack as being terminated:
terminate
...
self suspendedContext bottomContext push: #unwindingInTerminate. "<------- this marks receiver's stack as being terminated"
...
Please let me know if anybody has any concerns about borrowing the bottom context's stack top during termination :)
Thanks!
best,
~~~
^[^ Jaromir
Sent from Squeak Inbox Talk
On 2022-01-10T18:36:42+01:00, mail at jaromir.net wrote:
> Hi Christoph,
>
> Eliot's fix raises the 'infinite recursion' only when you Proceed the debugger without any change, i.e. attempting to evaluate the same unknown message; what's the scenario you've had in mind and what am I missing here? :)
>
> Oh, wait - did you mean you'd defined the unknown method in the wrong class so it only looked like nothing changed?
>
> In that case yes, #dnu will give you the 'infinite recursion' error because from it's point of view 'nothing changed'.
>
> The 'infinite recursion' guard is nice to have to prevent infinite recursion when you work with an MNU inside the ensure argument block. #terminateAggressively avoids this recursion by skipping halfway unwound blocks; at a price though: I've recently noticed when you abandon the debugger with a process inside a critical section of a conditional variable (Mutex, Semaphore) it wouldn't release the critical section: it would leave the Mutex/Semaphore locked.
>
> Try this example:
>
> Mutex new inspect critical: [1/0]
>
> do-it, a debugger opens, step into a few times until you stand right before #primitiveExitCriticalSection, hit Abandon - and watch the owner of the Mutex
>
> The Mutex will remain *locked* by a terminated process.
>
> The reason is #releaseCriticalSection: assumes #terminate will finish unwinding the innermost unwind context regardless whether it has already started or not yet - i.e. #releaseCriticalSection: expects #teminate to release the Mutex or signal the Semaphore.
>
> Unfortunately this is a general scenario: such behavior will happen whenever you Abandon a debugger inside an ensure argument block.
>
> So back to the MNU problem; we may need the classic terminate to try to correctly release critical sections and then the MNU 'infinite recursion' fix needs to be present;
>
> or, maybe just restrict Eliot's fix to only kick in for MNU errors inside ensure argument blocks... I haven't thought this through yet though :)
>
> Just FYI, the above scenario inspired this test (in the Inbox):
>
> testMutexInCriticalEnsureArgument "self run: #testMutexInCriticalEnsureArgument"
> "This tests whether a process that is in the ensure argument block in critical: but has yet to evaluate the primitiveExitCriticalSection
> leaves it with the mutex unlocked."
>
> | terminatee mutex |
> mutex := Mutex new.
> terminatee := [mutex critical: []] newProcess.
> self assert: terminatee isSuspended.
> terminatee runUntil: [:ctx | ctx selectorToSendOrSelf = #primitiveExitCriticalSection].
> self assert: terminatee isSuspended.
> terminatee terminate.
> self deny: mutex isOwned.
> self assert: mutex isEmpty
>
> Thanks for any comments,
>
> best,
> ~~~
> ^[^ Jaromir
>
> Sent from Squeak Inbox Talk
>
> On 2022-01-10T12:29:26+00:00, christoph.thiede at student.hpi.uni-potsdam.de wrote:
>
> > Hi all, hi Eliot, hi Jaromir,
> >
> >
> > in the last time, I observed a number of "Error: infinite recursion in doesNotUnderstand:" messages when proceeding from a DNU in the debugger. Would it be possible to disarm this again? I admit that I have not yet followed up the full background on this change, but ...:
> >
> >
> > My usual workflow looks like this: Observe a DNU, create a new message in order to *probably* fix the issue, and press Proceed to give it a second try. If my fix was incorrect, observe a second DNU, approach a second fix, and proceed again for a third try, etc. With the recent changes to #doesNotUnderstand:, I have only got one chance to make the right fix, i.e., implement the missing method on the right class in the first attempt. If I just evaluate "nil foo" and press Proceed two consecutive times, I get this "infinite recursion" error and my iterative development cycle is broken. :-( Can we fix this?
> >
> >
> > Long-term note: Sometime after the release(tm) I would like to revise the debugger's buttons to handle exceptions anyway, e.g., we could integrate a "retry" button for DNUs. But until then, I would really appreciate it if we could keep the existing workflows intact. Anyway, IMHO proceeding from a non-resumable exception should either) retry the operation recursively or) ignore the exception and resume right after it. At the moment, I have the feeling that we have reached neither of these directions for #doesNotUnderstand:. See also the analogous behavior in Object >> #at:. :-)
> >
> >
> > Thanks in advance!
> >
> >
> > Best,
> >
> > Christoph
> > -------------- next part --------------
> > An HTML attachment was scrubbed...
> > URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220110/58ec15da/attachment.html>
> >
> >
>
>
More information about the Squeak-dev
mailing list
|