help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] [PATCH] interesting corner case of nested exception han


From: Paolo Bonzini
Subject: [Help-smalltalk] [PATCH] interesting corner case of nested exception handlers
Date: Sun, 01 Jun 2008 19:36:38 +0200
User-agent: Thunderbird 2.0.0.14 (Macintosh/20080421)

This corner case is triggered by this simple snippet

    [[self error: 'abc']
                on: Exception do: [ :ex | 'bad' printNl ]
                on: Error do: [ :ex | ex pass ]]
        on: Error do: [ :ex | 'ok' printNl ]

The second exception handler is triggered and passes to the outer exception handler. However, the first handler (the one for Exception) is never disabled, so #pass triggers that exception handler instead of the outer one!

This is easily fixed -- even if only the "best" handler is chosen, all of them should be disabled.

Paolo
commit f4c89de35854ee944cdec488b68c45003885369c
Author: Paolo Bonzini <address@hidden>
Date:   Sun Jun 1 19:21:42 2008 +0200

    fix weird case of nested exception handlers and #pass
    
    2008-06-01  Paolo Bonzini  <address@hidden>
    
        * kernel/BlkClosure.st: Fix weird case of #on:do:on:do:on:do:.
        * tests/exceptions.st: Add test case.
        * tests/exceptions.ok: Regenerate.

diff --git a/ChangeLog b/ChangeLog
index b060faf..6b1052f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2008-06-01  Paolo Bonzini  <address@hidden>
 
+       * kernel/BlkClosure.st: Fix weird case of #on:do:on:do:on:do:.
+       * tests/exceptions.st: Add test case.
+       * tests/exceptions.ok: Regenerate.
+
+2008-06-01  Paolo Bonzini  <address@hidden>
+
        * kernel/URL.st: Fix redirects including a GET query.
        Add #contents and #readStream.
 
diff --git a/kernel/BlkClosure.st b/kernel/BlkClosure.st
index 6e7bca3..2b635bf 100644
--- a/kernel/BlkClosure.st
+++ b/kernel/BlkClosure.st
@@ -70,27 +70,27 @@ creation of Processes from blocks.'>
                                [(activeHandlers bitAt: i) = 1 
                                    ifTrue: 
                                        ["Sorry, this handler is already 
active..."
+                                       nested := true]
+                                   ifFalse:
+                                       [activeHandlers := activeHandlers 
setBit: i.
+                                       goodness > bestGoodness 
+                                           ifTrue: 
+                                               [best := i.
+                                               bestGoodness := goodness]]]]].
 
-                                       nested := true.
-                                       goodness := -1]].
-                       goodness > bestGoodness 
-                           ifTrue: 
-                               [best := i.
-                               bestGoodness := goodness]]].
+       context at: context numArgs + 1 put: activeHandlers.
 
        "Now instantiate the best handler we found"
        best isNil 
            ifFalse: 
-               [context at: context numArgs + 1 put: (activeHandlers setBit: 
best).
-               signal 
+               [signal 
                    onDoBlock: context receiver
                    handlerBlock: (context at: best + 1)
                    onDoContext: context
                    previousState: activeHandlers.
                #found]
            ifTrue: 
-               [context at: context numArgs + 1 put: activeHandlers.
-               nested ifTrue: [#skip] ifFalse: [nil]]]
+               [nested ifTrue: [#skip] ifFalse: [nil]]]
     ]
 
     BlockClosure class >> numArgs: args numTemps: temps bytecodes: bytecodes 
depth: depth literals: literalArray [
diff --git a/tests/exceptions.ok b/tests/exceptions.ok
index c54128e..5fbf15c 100644
--- a/tests/exceptions.ok
+++ b/tests/exceptions.ok
@@ -19,6 +19,11 @@ returned value is TextCollector new "<0>"
 
 Execution begins...
 
+testPass (2)...passing...ok
+returned value is TextCollector new "<0>"
+
+Execution begins...
+
 testEnsure... error:  Ignore this error
 passed
 returned value is nil
diff --git a/tests/exceptions.st b/tests/exceptions.st
index 377411e..4c06f5d 100644
--- a/tests/exceptions.st
+++ b/tests/exceptions.st
@@ -76,6 +76,18 @@ Eval [
 ]
 
 Eval [
+    "Test that passing disables all exception handlers in the #on:do: snippet."
+
+    Transcript cr; show: 'testPass (2)...'.
+    [[self error: 'abc']
+               on: Exception do: [ :ex | Transcript show: 'failed' ]
+               on: Error do: [ :ex | Transcript show: 'passing...'. ex pass ]]
+       on: Error do: [ :ex | Transcript show: 'ok' ].
+
+    Transcript cr
+]
+
+Eval [
     [   Transcript cr; show: 'testEnsure...'.
             self error: ' Ignore this error']
         ensure: [Transcript show: 'passed'; cr]

reply via email to

[Prev in Thread] Current Thread [Next in Thread]