I will collect here other issues if I will find them. Looking in Context methods which I mentioned here I found that debugger is broken for stepping through warnings. And it means that debugging deprecated methods can hang debugger.
I will create another thread on this issue because it has more questions on current exceptions design. чт, 19 дек. 2019 г. в 18:39, Denis Kudriashov <dionisi...@gmail.com>: > The solution to problem is to resignal UnhandledError instead of simple > signalling. Resignal uses original signalContext as a starting point for > handlers lookup: > > UnhandledError>>signalForException: anError > > ^anError resignalAs: (self new > > exception: anError; > > yourself) > > > I played with some of debugger issues and this code really fixes them. > For example try debug following script in playground: > > [ > self methodWithError > ] on: Error do: [ :e | e logCr. e pass ] > > With error method: > > > Object>>methodWithError > > 1/0 > > Step into #methodWithError and then stepThrough "1/0". > In current image it will hands for a while and then it will open another > debugger with single error item. The current debugger process will be > broken. > Now try to apply proposed change for UnhandledError>>signalForException: > and repeat experiment. StepThrough "1/0" will move debugger to ZeroDivide > signal showing correct stack. > > > Notice that debugging separate "self methodWithError" without outer > handler works correctly in both cases. But you should be in clean stack > without hidden outer handlers. And in Playground or when you use debugIt it > is clean. > But you can try in "bad" environment. Execute in browser editor "self > halt. self methodWithError". And in debugger just Step Through > #methodWithError. It will hangs. Proposed change fixes that. > > I will prepare PR with tests. But it would be nice to find other broken > places which will be fixed > > чт, 19 дек. 2019 г. в 00:42, Denis Kudriashov <dionisi...@gmail.com>: > >> I think this problem could lead to debugger issues with stepOver and >> stepThrough. For example: >> >> Context>>#stepToHome: >> ... >> context := aContext insertSender: (Context >> contextOn: UnhandledError do: [:ex | ... ]) >> >> It is a method which is used for stepThrough. If current method has outer >> handler for Error then the UnhandledError logic will be ignored. >> >> Step over is based on following method: >> >> Context>>runUntilErrorOrReturnFrom: aSender >> ... >> >> context := aSender insertSender: (Context >> >> contextOn: Error do: [:ex | >> >> error ifNil: [ >> >> "this is ugly but it fixes the side-effects of not sending an >> Unhandled error on Halt" >> >> error := (ex isKindOf: UnhandledError) ifTrue: [ ex exception ] >> ifFalse: [ ex ]. >> ... >> >> I think UnhandledError branch will never be true: >> >> [ 1/0 ] on: Error do: [:e | e logCr. e3 pass ] >> >> Handler here is executed only once with ZeroDivide error. >> Previous version was based on UnhandledError handler: >> >> >> context := aSender insertSender: (Context >> contextOn: UnhandledError, Halt do: [:ex | ...] >> >> >> which had the same issue when there is an outer error handler. >> And we have such general error handler (probably introduced in Pharo 6): >> >> WorldMorph>>becomeActiveDuring: aBlock >> >> ... >> >> aBlock >> >> on: Error >> >> do: [ :ex | ... ex pass ] >> >> >> Any UI event is processed under this method. >> >> ср, 18 дек. 2019 г. в 22:31, Denis Kudriashov <dionisi...@gmail.com>: >> >>> Users of UnhandledError definitely shows that it is a critical bug. >>> >>> For example we rely on UnhandledError in Announcer to ensure that all >>> subscriptions will be processed independently on errors signalled by any of >>> them: >>> >>> ann := Announcer new. >>> ann when: ValueChanged do: [:ann | 1 logCr. 1/0 ]. >>> ann when: ValueChanged do: [:ann | 2 logCr. 2/0 ]. >>> ann when: ValueChanged do: [:ann | 3 logCr. 3/0 ]. >>> >>> >>> ann announce: ValueChanged new >>> >>> >>> It will show 1, 2, 3 in transcript and open 3 debuggers. Each error is >>> deferred to the background process allowing the delivery to continue: >>> >>> AnnouncementSubscription>>deliver: anAnnouncement >>> >>> " deliver an announcement to receiver. In case of failure, it will be >>> handled in separate process" >>> >>> >>> ^ (self handlesAnnouncement: anAnnouncement ) ifTrue: [ >>> >>> [action cull: anAnnouncement cull: announcer] >>> >>> on: UnhandledError fork: [:ex | ex pass ]] >>> >>> >>> Now if you will try to wrap #announce: into handler block the deliver >>> will be interrupted by first error: >>> >>> [ann announce: ValueChanged new] on: ZeroDivide do: [ :err | err logCr. >>> err pass ]. >>> >>> >>> It will open single debugger at first handler error. >>> >>> ср, 18 дек. 2019 г. в 20:44, Denis Kudriashov <dionisi...@gmail.com>: >>> >>>> Hi. >>>> >>>> I played a bit with exceptions trying to detect that given block will >>>> open the debugger. My idea was to simply catch UnhandledError which >>>> normally means that no outer code handles given error and therefore >>>> debugger is appeared. >>>> For my surprise the following example works from playground but not >>>> from the browser editor: >>>> >>>> >>>> [MyTestError signal ] on: UnhandledError do: [ :e | self halt ] >>>> >>>> >>>> In playground you will see the halt. But from the browser the debugger >>>> will show MyTestError. >>>> >>>> After breaking my head I found that there is a difference how >>>> scripts are executed in those tools. In Playground it is a deferred action. >>>> But in the browser it is evaluated as a deep event processing code (keymap >>>> processing) and there is an outer error handler (on: Error do: ) which does >>>> some work and passes the exception further (err pass). >>>> Following script demonstrates the difference in the error processing >>>> logic when there is an outer handler: >>>> >>>> >>>> [ >>>> >>>> [MyTestError signal ] on: UnhandledError do: [ :e | self halt ] >>>> >>>> ] on: MyTestError do: [ :z | z pass] >>>> >>>> >>>> Try it from playground. Second line separately will show the halt while >>>> all together it will stop at MyTestError signal. >>>> >>>> Debugging shows that when the outer handler is processed it sets the >>>> handler context into the exception and it skips the existing handler for >>>> UnhandledError. >>>> >>>> The question: is it a feature or a bug? >>>> Think also how following code should work (unrelated to UnhandledError >>>> logic): >>>> >>>> [ >>>> >>>> [ 1/0 ] on: MyTestError do: [ :e | self halt ] >>>> >>>> ] on: ZeroDivide do: [ :z | MyTestError signal ] >>>> >>>> >>>> Currently it will show MyTestError signal. >>>> >>>> Best regards, >>>> Denis >>>> >>>