[PATCH] interesting corner case of nested exception handlers

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] interesting corner case of nested exception handlers

Paolo Bonzini-2
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 <[hidden email]>
Date:   Sun Jun 1 19:21:42 2008 +0200

    fix weird case of nested exception handlers and #pass
   
    2008-06-01  Paolo Bonzini  <[hidden email]>
   
    * 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  <[hidden email]>
 
+ * 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  <[hidden email]>
+
  * 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]

_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk