Why is ModificationForbidden not an Error?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
44 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Why is ModificationForbidden not an Error?

Christoph Thiede

Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

Possibly related stuff:


Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Eliot Miranda-2
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.



Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Jakob Reschke-2
Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.


Eliot Miranda <[hidden email]> schrieb am Do., 9. Apr. 2020, 17:04:
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.




Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Christoph Thiede
In reply to this post by Eliot Miranda-2

Thanks for the fast feedback, I am going to commit this to the Inbox!


Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.

Exactly, that was also my original motivation to ask this question :-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 9. April 2020 17:03:59
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.



Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Chris Muller-3
ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.

Proper signaling and handling are independent of each other.  Please evaluate your decision from the handling side too -- whether it'd be better for TestRunner's handling to include ModificationForbidden.

 - Chris

On Thu, Apr 9, 2020 at 12:44 PM Thiede, Christoph <[hidden email]> wrote:

Thanks for the fast feedback, I am going to commit this to the Inbox!


Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.

Exactly, that was also my original motivation to ask this question :-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 9. April 2020 17:03:59
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.




Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Christoph Thiede

ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.


-1. :-) Warnings are Notifications, and Notifications are characterized by their property not to have any side-effects on the core operation unless handled by any caller. (A second type of Notification is used for requesting some value that can be answered by any handler, but the overall effect is the same.) See Notification >> #defaultAction and its class comment.

If a ModificationForbidden exception is resumed, the object keeps unmodified, so this is a kinda dangerous resumption. That's also why the defaultAction of a MF is not to resume the execution but to raise an UnhandledError instead, which, IMHO, is the (only) right way to handle the event that a low-level operation could not be executed as you would have expected.


I would never expect the following to evaluate to 0 because any far-away caller could resume every possible MF:

#(0) at: 1 put: 1; first

How could you write reliable code if you had to make such assumptions? I believe that this would lead us to crazy shambles where you had to question every obvious fact.


Warnings say: You shouldn't do this, or maybe you don't actually want to do this, but it is possible to continue doing so, so we won't stop you from doing so until you decide otherwise.

Errors say: You can't do this, and we won't permit that attempt, so you can either decide to actively ignore this error and skip to the next statement, or we'll blow up the execution (and almost ever open a Debugger).


At least this is what I could learn from Squeak's exception framework until now. As always, I'm open for new perspectives :-)

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Chris Muller <[hidden email]>
Gesendet: Freitag, 10. April 2020 00:15 Uhr
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.

Proper signaling and handling are independent of each other.  Please evaluate your decision from the handling side too -- whether it'd be better for TestRunner's handling to include ModificationForbidden.

 - Chris

On Thu, Apr 9, 2020 at 12:44 PM Thiede, Christoph <[hidden email]> wrote:

Thanks for the fast feedback, I am going to commit this to the Inbox!


Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.

Exactly, that was also my original motivation to ask this question :-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 9. April 2020 17:03:59
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.




Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Eliot Miranda-2
In reply to this post by Chris Muller-3
Hi Chris,


On Apr 9, 2020, at 3:16 PM, Chris Muller <[hidden email]> wrote:


ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.

One can override isResumable. There’s no invariant that’s a subclass of Error can’t be resumable.  IMO many more Error subclasses that aren’t should be isResumable.



Proper signaling and handling are independent of each other.  Please evaluate your decision from the handling side too -- whether it'd be better for TestRunner's handling to include ModificationForbidden.

 - Chris

On Thu, Apr 9, 2020 at 12:44 PM Thiede, Christoph <[hidden email]> wrote:

Thanks for the fast feedback, I am going to commit this to the Inbox!


Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.

Exactly, that was also my original motivation to ask this question :-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 9. April 2020 17:03:59
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.





Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Chris Muller-4
In reply to this post by Christoph Thiede
Hi Christoph,

I having trouble figuring out whether your points are primarily about semantics or mechanics..
 

ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.

-1. :-) Warnings are Notifications,

As are Errors.  Right?

and Notifications are characterized by their property not to have any side-effects on the core operation unless handled by any caller.

Mmmm, I'm not sure what point you're making here.  Mechanically, they're all basically the same.  See?

     Notification signal. 'resumed'.         "resumed"
     Warning signal.  'resumed'.             "(click Proceed) resumed"
     Error signal. 'resumed'                    "(click Proceed) resumed"

The fact that Errors can be resumed is a flat out bug, IMO, but they can...

If a ModificationForbidden exception is resumed, the object keeps unmodified, so this is a kinda dangerous resumption.

"Dangerous" how so?  There's no escaping that ModificationForbidden introduces new complexity if one isn't aware of it and how it works -- whether they use it or not, even -- could be in for some unexpected surprises in any case..
 

That's also why the defaultAction of a MF is not to resume the execution but to raise an UnhandledError instead, which, IMHO, is the (only) right way to handle the event that a low-level operation could not be executed as you would have expected.

And exactly how a Warning behaves...

    Warning signal    "unhandled, debugger appears"
    Notification signal    "unhandled, debugger does not appear"
    [ Warning signal ] on: Warning do: [ : warn | warn resume ]    "handled, debugger does not appear" 

In every mechanical way so far, we've seen that Warning is closer to Error than it is to Notification.

I would never expect the following to evaluate to 0 because any far-away caller could resume every possible MF:

#(0) at: 1 put: 1; first


Which has no bearing on whether its categorized as a Warning or Error... 
 

How could you write reliable code if you had to make such assumptions? I believe that this would lead us to crazy shambles where you had to question every obvious fact


I'm sorry Christoph.  I must've missed your point.  MF needs to be able to be resumed.  Squeak allows any Error to be resumed, but this fails your semantic definition, below...
 

Warnings say: You shouldn't do this, or maybe you don't actually want to do this, but it is possible to continue doing so, so we won't stop you from doing so until you decide otherwise.

Which is EXACTLY what ModificationForbidden is..!
 

Errors say: You can't do this, and we won't permit that attempt, so you can either decide to actively ignore this error and skip to the next statement, or we'll blow up the execution (and almost ever open a Debugger).

And why it's precisely wrong for ModificationForbidden.  See above.  If you "can't do this", why would you want to allow it to be resumed?   This is why only the most exceptional Errors are declared resumable (even though it's functionally meaningless, just "documentation").  The vast majority of Errors are not resumable.

 - Chris 


Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Chris Muller-4
In reply to this post by Eliot Miranda-2
Hi Eliot,

Right, ALL errors are mechanically resumable, regardless of #isResumable.  See?

   [ Error signal. 'resumed' ] on: Error do: [ : err | err resume ]         "resumed"

... so we're just talking about proper semantics.  Given your statements, what differentiates for you, a Warning vs. a resumable Error.   To me, the latter seems like a misnomer...

On Thu, Apr 9, 2020 at 6:21 PM Eliot Miranda <[hidden email]> wrote:
Hi Chris,


On Apr 9, 2020, at 3:16 PM, Chris Muller <[hidden email]> wrote:


ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.

One can override isResumable. There’s no invariant that’s a subclass of Error can’t be resumable.  IMO many more Error subclasses that aren’t should be isResumable.



Proper signaling and handling are independent of each other.  Please evaluate your decision from the handling side too -- whether it'd be better for TestRunner's handling to include ModificationForbidden.

 - Chris

On Thu, Apr 9, 2020 at 12:44 PM Thiede, Christoph <[hidden email]> wrote:

Thanks for the fast feedback, I am going to commit this to the Inbox!


Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.

Exactly, that was also my original motivation to ask this question :-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 9. April 2020 17:03:59
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.





Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Chris Muller-3
In reply to this post by Chris Muller-4
After further thought, I think you're right that it shouldn't inherit from Warning, because it could get accidentally resumed unintentionally by some high-level handler like SmalltalkImage>>#run:.

The two main use cases of ModificationForbidden present opposite perspectives onto it.  For "protection from accidentally modifying a literal in a CompiledMethod", I understand the inclination to make it an Error.  However, for the context of db handling, [#markDirty + #resume] is normal processing, not an "error", and not even exceptional, either, so perhaps this is just a semantic irritation sensitivity on my part.. sorry.   Inheriting from Error is probably the most convenient way to preserve the CompiledMethod protection use case.  Though, I think it's worth considering sprinkling some handlers of ModificationForbidden as an alternative.

 - Chris

On Thu, Apr 9, 2020 at 7:18 PM Chris Muller <[hidden email]> wrote:
Hi Christoph,

I having trouble figuring out whether your points are primarily about semantics or mechanics..
 

ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.

-1. :-) Warnings are Notifications,

As are Errors.  Right?

and Notifications are characterized by their property not to have any side-effects on the core operation unless handled by any caller.

Mmmm, I'm not sure what point you're making here.  Mechanically, they're all basically the same.  See?

     Notification signal. 'resumed'.         "resumed"
     Warning signal.  'resumed'.             "(click Proceed) resumed"
     Error signal. 'resumed'                    "(click Proceed) resumed"

The fact that Errors can be resumed is a flat out bug, IMO, but they can...

If a ModificationForbidden exception is resumed, the object keeps unmodified, so this is a kinda dangerous resumption.

"Dangerous" how so?  There's no escaping that ModificationForbidden introduces new complexity if one isn't aware of it and how it works -- whether they use it or not, even -- could be in for some unexpected surprises in any case..
 

That's also why the defaultAction of a MF is not to resume the execution but to raise an UnhandledError instead, which, IMHO, is the (only) right way to handle the event that a low-level operation could not be executed as you would have expected.

And exactly how a Warning behaves...

    Warning signal    "unhandled, debugger appears"
    Notification signal    "unhandled, debugger does not appear"
    [ Warning signal ] on: Warning do: [ : warn | warn resume ]    "handled, debugger does not appear" 

In every mechanical way so far, we've seen that Warning is closer to Error than it is to Notification.

I would never expect the following to evaluate to 0 because any far-away caller could resume every possible MF:

#(0) at: 1 put: 1; first


Which has no bearing on whether its categorized as a Warning or Error... 
 

How could you write reliable code if you had to make such assumptions? I believe that this would lead us to crazy shambles where you had to question every obvious fact


I'm sorry Christoph.  I must've missed your point.  MF needs to be able to be resumed.  Squeak allows any Error to be resumed, but this fails your semantic definition, below...
 

Warnings say: You shouldn't do this, or maybe you don't actually want to do this, but it is possible to continue doing so, so we won't stop you from doing so until you decide otherwise.

Which is EXACTLY what ModificationForbidden is..!
 

Errors say: You can't do this, and we won't permit that attempt, so you can either decide to actively ignore this error and skip to the next statement, or we'll blow up the execution (and almost ever open a Debugger).

And why it's precisely wrong for ModificationForbidden.  See above.  If you "can't do this", why would you want to allow it to be resumed?   This is why only the most exceptional Errors are declared resumable (even though it's functionally meaningless, just "documentation").  The vast majority of Errors are not resumable.

 - Chris 



Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Jakob Reschke-2
In reply to this post by Chris Muller-4
Hi Chris, hi all,

If I do this:

    [ Error signal. 'resumed' ] on: Error do: [ : err | err resume ]

I get an IllegalResumeAttempt exception, as it should be. Developers
or Squeak app users can always press Proceed (and hopefully they now
what they are doing), but you cannot "click proceed" in any regular
error handling code. So you cannot proceed non-resumable exceptions
in, for example, unattended batch jobs.

SmalltalkCI is such an unattended job, and I would like a test case to
fail in error because of ModificationForbidden. I neither want it to
halt the whole test suite (as it does now), nor to silently continue
as if there were no problem in the tested code.

Concerning the discussion how to sort it into the class hierarchy: we
should probably just think about which kinds of existing error
handlers should catch it. This makes it a question of compatibility
with existing code.
- on: Error do: cannot resume, but can be used to skip over the rest
of an operation and continue with the next work item. Errors are
caught by SUnit and smalltalkCI.
- on: Warning do: can resume, and I believe it will in most of the
cases, maybe with some logging involved. Warnings are not handled by
SUnit or smalltalkCI, but by SmalltalkImage>>#run:
- on: Notification do: can resume, but I am not sure why one would
write such a handler for all kinds of Notifications.
- on: Exception do: [:ex | ex isResumable ifTrue: [ex resume] ...] can
obviously resume, the intention is clear, but I don't think this is a
common idiom, is it?
- on: ModificationForbidden do: can resume and would be the ideal
choice to overcome our concerns, of course, but it is not found in
existing code bases yet.

I suppose inheriting from Error is "fail-safest", but not necessarily
fail-operational. Unattended services that somehow worked with the old
ways may break. If we don't want to break things (that are somehow
wrong according to contemporary notion), we could make it a Warning in
the Squeak 5.x release stream and turn it into an error with Squeak
6.0. That is: make it an Error today in Trunk, but if we would create
a 5.4 release, we would have to remember changing it back... :-/

Kind regards,
Jakob

Am Fr., 10. Apr. 2020 um 02:18 Uhr schrieb Chris Muller <[hidden email]>:

>
> Hi Eliot,
>
> Right, ALL errors are mechanically resumable, regardless of #isResumable.  See?
>
>    [ Error signal. 'resumed' ] on: Error do: [ : err | err resume ]         "resumed"
>
> ... so we're just talking about proper semantics.  Given your statements, what differentiates for you, a Warning vs. a resumable Error.   To me, the latter seems like a misnomer...
>
> On Thu, Apr 9, 2020 at 6:21 PM Eliot Miranda <[hidden email]> wrote:
>>
>> Hi Chris,
>>
>>
>> On Apr 9, 2020, at 3:16 PM, Chris Muller <[hidden email]> wrote:
>>
>> 
>> ModificationForbidden is resumable like a Warning, and unlike most Errors.  Perhaps it should be a Warning.
>>
>>
>> One can override isResumable. There’s no invariant that’s a subclass of Error can’t be resumable.  IMO many more Error subclasses that aren’t should be isResumable.
>>
>>
>>
>> Proper signaling and handling are independent of each other.  Please evaluate your decision from the handling side too -- whether it'd be better for TestRunner's handling to include ModificationForbidden.
>>
>>  - Chris
>>
>> On Thu, Apr 9, 2020 at 12:44 PM Thiede, Christoph <[hidden email]> wrote:
>>>
>>> Thanks for the fast feedback, I am going to commit this to the Inbox!
>>>
>>>
>>> > Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.
>>>
>>> Exactly, that was also my original motivation to ask this question :-)
>>>
>>> Best,
>>> Christoph
>>> ________________________________
>>> Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
>>> Gesendet: Donnerstag, 9. April 2020 17:03:59
>>> An: The general-purpose Squeak developers list
>>> Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
>>>
>>> Hi Christoph,
>>>
>>>
>>> On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:
>>>
>>> 
>>>
>>> Hi all,
>>>
>>>
>>> please take a short look at this behavior:
>>>
>>>
>>> TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"
>>>
>>>
>>> At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
>>> I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
>>> (Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)
>>>
>>> So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
>>> I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?
>>>
>>>
>>> I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.
>>>
>>> Please feel free to make it an Error.
>>>
>>>
>>> Possibly related stuff:
>>>
>>> http://forum.world.st/Squeak-s-AssertionFailure-vs-SUnit-s-TestFailure-td5106818.html
>>> http://forum.world.st/The-Trunk-Kernel-eem-1294-mcz-td5112196.html
>>> http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-tp5113273p5113433.html
>>>
>>>
>>> Best,
>>> Christoph
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

timrowledge
In reply to this post by Chris Muller-3


> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>
> The two main use cases of ModificationForbidden present opposite perspectives onto it.

In that case perhaps we actually need two different signals?

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Has an inferiority complex, but not a very good one.



Reply | Threaded
Open this post in threaded view
|

How May We Assist?

Renters Cancellation Requests
In reply to this post by Jakob Reschke-2

Dear Valued Customer,


Thank you for your inquiry. Please let us know how we may assist you.


If you have a Renter’s policy, you can manage your policy online 24/7 at: https://www.myassurantpolicy.com/

You have access to a range of service options including:

  • View/update policy information
  • Manage your payments
  • Obtain proof of insurance
  • And much more


Thank you for allowing us the opportunity to serve you.


Sincerely,

Insurance Services

Assurant - Global Specialty Operations 





------------------- Original Message -------------------
From: Jakob Reschke
Received: Thu Apr 09 2020 12:13:00 GMT-0400 (Eastern Daylight Time)
To: gettimothy via Squeak-dev
Subject: Re: [squeak-dev] Why is ModificationForbidden not an Error?


Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.


Eliot Miranda <[hidden email]> schrieb am Do., 9. Apr. 2020, 17:04:
Hi Christoph,


On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all,


please take a short look at this behavior:


TestRunner openForSuite: MorphicUIManagerTest suite. "Run Selected"


At the moment (#19541), a bug in FileList2 class >> #endingSpecs (which I'm going to fix ASAP) breaks the test #testShowAllBinParts. But because ModificationForbidden is not an Error, it is not caught by the TestRunner so the whole suite run blows up, too.
I could make another example by triggering a ModificationForbidden in a #drawOn: method to destroy the whole image, too.
(Morph newSubclass compile: 'drawOn: x #(1) at: 1 put: 2'; new) openInHand)

So my question is: Why doesn't ModificationForbidden derive from Error? Isn't it actually an error? Similar illegal operations such as "#() at: 0" or "{} at: 1 put: #foo" raise some kind of Error, too. Everything I learned so far about Squeak's exception framework tells me that you should have a very good reason if you design an exception neither to derive from Error, nor from Notification. At the moment, we only do have 9 exceptions (bad pun ...) to this rule (and I'm not even sure whether MCNoChangesException couldn't be a notification, and Abort does not even have senders in the Trunk).
I'd be happy if you could give me some pointers on why ModificationForbidden does not follow this rule. How can we deal with this in order to fix the bugs/unexpected behaviors mentioned above?

I think this is an oversight in my part.  I agree that ModificationForbidden is an error.  I took the code from Pharo and didn’t notice ModificationForbidden was a Notification.



This e-mail message and all attachments transmitted with it may contain legally privileged and/or confidential information intended solely for the use of the addressee(s). If the reader of this message is not the intended recipient, you are hereby notified that any reading, dissemination, distribution, copying, forwarding or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately and delete this message and all copies and backups thereof. Thank you.



ATT00001.txt (6 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Chris Muller-3
In reply to this post by Jakob Reschke-2
If I do this:

    [ Error signal. 'resumed' ] on: Error do: [ : err | err resume ]

I get an IllegalResumeAttempt exception, as it should be. Developers
or Squeak app users can always press Proceed (and hopefully they now
what they are doing), but you cannot "click proceed" in any regular
error handling code. So you cannot proceed non-resumable exceptions
in, for example, unattended batch jobs.

You're right.  I fooled myself In my quick test, I had only written the code in the block:

     Error signal. 'resumed'

instead of writing the full handler like above, and noticed I was able to Proceed and get 'resumed' out of it.  It does indeed correctly check for IllegalResumeAttempt if you resume via #resume.  Sorry for that false alarm.

 - Chris


Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Eliot Miranda-2
In reply to this post by timrowledge


> On Apr 10, 2020, at 10:06 AM, tim Rowledge <[hidden email]> wrote:
>
> 
>
>> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>>
>> The two main use cases of ModificationForbidden present opposite perspectives onto it.
>
> In that case perhaps we actually need two different signals ?

No!  When the signal is raised there is no way to tell about the use case without eg raising an exception to query the dynamic environment.  We only need one signal and it should be a resumable error.

>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Useful random insult:- Has an inferiority complex, but not a very good one.
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Chris Muller-3
In reply to this post by timrowledge
I think so, because if you try to use it for something else, it'll get entangled with your application's standard error handling.  Regular apps have error handling like:

   [ myApp doStuff ] on: Error do: [ : err | myApp logErrorAndNotifyUser ]

and so for the use-case, Protect CompiledMethod Literals from Accidental Modification, inheriting from Error will allow the best backward compatibility with existing handlers.

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:

   [ myDbApp doStuff ]
     on: ModificationForbidden
     do:
          [ : forbidden |
          forbidden object beWritableObject.
          forbidden resumptionValue: forbidden retryModificationNoResume.
          forbidden resume: forbidden resumptionValue ]
     on: Error
     do: [ : err | myDbApp logErrorAndNotifyUser ]

But now that I'm handling ModificationForbidden separately, what if I want Protect CompiledMethod Literals from Accidental Modification, too?  I'm no longer handling correctly for that, because the handler has to assume they're signaled in the context of the DB use case and not the Protection use case.

 - Chris

On Fri, Apr 10, 2020 at 12:06 PM tim Rowledge <[hidden email]> wrote:


> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>
> The two main use cases of ModificationForbidden present opposite perspectives onto it.

In that case perhaps we actually need two different signals?

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Has an inferiority complex, but not a very good one.





Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Nicolas Cellier
In this case we might want specialized subclasses...

Le sam. 11 avr. 2020 à 03:45, Chris Muller <[hidden email]> a écrit :
I think so, because if you try to use it for something else, it'll get entangled with your application's standard error handling.  Regular apps have error handling like:

   [ myApp doStuff ] on: Error do: [ : err | myApp logErrorAndNotifyUser ]

and so for the use-case, Protect CompiledMethod Literals from Accidental Modification, inheriting from Error will allow the best backward compatibility with existing handlers.

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:

   [ myDbApp doStuff ]
     on: ModificationForbidden
     do:
          [ : forbidden |
          forbidden object beWritableObject.
          forbidden resumptionValue: forbidden retryModificationNoResume.
          forbidden resume: forbidden resumptionValue ]
     on: Error
     do: [ : err | myDbApp logErrorAndNotifyUser ]

But now that I'm handling ModificationForbidden separately, what if I want Protect CompiledMethod Literals from Accidental Modification, too?  I'm no longer handling correctly for that, because the handler has to assume they're signaled in the context of the DB use case and not the Protection use case.

 - Chris

On Fri, Apr 10, 2020 at 12:06 PM tim Rowledge <[hidden email]> wrote:


> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>
> The two main use cases of ModificationForbidden present opposite perspectives onto it.

In that case perhaps we actually need two different signals?

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Has an inferiority complex, but not a very good one.






Reply | Threaded
Open this post in threaded view
|

Re: Why is ModificationForbidden not an Error?

Christoph Thiede

Hi all! Thank you very much for having this interesting discussion :-)


@Chris:

> > -1. :-) Warnings are Notifications,

> As are Errors.  Right?

Nope, sorry ;-)
 

The two main use cases of ModificationForbidden present opposite perspectives onto it.  For "protection from accidentally modifying a literal in a CompiledMethod", I understand the inclination to make it an Error.  However, for the context of db handling, [#markDirty + #resume] is normal processing, not an "error", and not even exceptional, either, so perhaps this is just a semantic irritation sensitivity on my part.. sorry. 

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:
>    [ myDbApp doStuff ]
>      on: ModificationForbidden
>      do:
>           [ : forbidden |
>           forbidden object beWritableObject.
>           forbidden resumptionValue: forbidden retryModificationNoResume.
>           forbidden resume: forbidden resumptionValue ]
>      on: Error
>      do: [ : err | myDbApp logErrorAndNotifyUser ]

This clarification was very helpful for me. I was not aware of your second use case before.

In my opinion, we are talking about two completely different use cases for the same exception.
Literal protection is a low-level error, comparable to out-of-bounds things and primitive failures. You almost never do want to ignore or fix them.
Write barriers for #markDirty, on the other hand, sound like a domain-specific topic to me that should neither raise an error, nor eventually signal an UnhandledError, but be resumed automatically (unless handled differently) by a #defaultAction that removes the barrier (and additional handlers could, if desired, turn on some cache or so).
I have never dealt with Magma or any other DB framework for Smalltalk, but why do you (or would you) use these VM-based mechanisms for a high-level feature? Without knowing any details about your application, personally I would probably design an own exception (DirtyModification?) for that purpose. This would allow you to clearly distinguish between low-level errors ("whoops, I just made an attempt to change a read-only code literal") and higher-level exceptions (DirtyModification). If we would follow my proposal to raise ModificationForbidden from Object instead of Context, you could also consider to override #modificationForbiddenFor:at:put: in your database objects to raise DirtyModification instead of ModificationForbidden (in the same way as some classes override #error or #primitiveError).

However, focusing again on the literal protection aspect, I still don't see when the current default #resume behavior of ModificationForbidden would be ever helpful. MF >> #resume calls Exception >> #resume: which does nothing more than to return resumptionValue! When do we actually need this resumptionValue?
Why can't we design MF like the following:

#resume - not possible, will signal IllegalResumeAttempt
#retryModification - retries the modification and returns nothing special
#forceModification: - makes the object to modify writable, retries the modification and, optionally, makes the object read-only again

If we don't want to break things (that are somehow wrong according to contemporary notion), we could make it a Warning in the Squeak 5.x release stream and turn it into an error with Squeak 6.0. That is: make it an Error today in Trunk, but if we would create a 5.4 release, we would have to remember changing it back... :-/

IIRC ModificationForbidden was introduced in 6.0alpha the first time?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]>
Gesendet: Samstag, 11. April 2020 11:16:00
An: Chris Muller; The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
In this case we might want specialized subclasses...

Le sam. 11 avr. 2020 à 03:45, Chris Muller <[hidden email]> a écrit :
I think so, because if you try to use it for something else, it'll get entangled with your application's standard error handling.  Regular apps have error handling like:

   [ myApp doStuff ] on: Error do: [ : err | myApp logErrorAndNotifyUser ]

and so for the use-case, Protect CompiledMethod Literals from Accidental Modification, inheriting from Error will allow the best backward compatibility with existing handlers.

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:

   [ myDbApp doStuff ]
     on: ModificationForbidden
     do:
          [ : forbidden |
          forbidden object beWritableObject.
          forbidden resumptionValue: forbidden retryModificationNoResume.
          forbidden resume: forbidden resumptionValue ]
     on: Error
     do: [ : err | myDbApp logErrorAndNotifyUser ]

But now that I'm handling ModificationForbidden separately, what if I want Protect CompiledMethod Literals from Accidental Modification, too?  I'm no longer handling correctly for that, because the handler has to assume they're signaled in the context of the DB use case and not the Protection use case.

 - Chris

On Fri, Apr 10, 2020 at 12:06 PM tim Rowledge <[hidden email]> wrote:


> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>
> The two main use cases of ModificationForbidden present opposite perspectives onto it.

In that case perhaps we actually need two different signals?

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Has an inferiority complex, but not a very good one.






Reply | Threaded
Open this post in threaded view
|

Debugger - Proceed button (was: Why is ModificationForbidden not an Error?)

Christoph Thiede

Just another thought: I see some confusion around the Proceed button in the debugger, and I felt the same confusion sometimes ago. Please forgive me for the sacrilege, but should we maybe question its general existence?

Depending on the domain, it actually performs a mix of #retry (made possible by the quite <a href="http://forum.world.st/I-broke-the-debugger-td5110752.html#a5112307#:~:text=recursively" class="OWAAutoLink" style="font-size: 12pt;">confusing recursive implementation of Object >> #at:, Object >> #doesNotUnderstand: and others, I did not yet found any other motivation than the Proceed button to use recursion here) and ignore (#resumeUnchecked:, especially useful for UnhandledWarnings and Halts). Would it be a reasonable goal to eliminate this button in the pre-debugger window and replace it with two buttons, Restart and Ignore? We could hide even hide the restart button if not appropriate (i.e., the exception is not an error).

What do you think?
And it would be great if anyone here could explain why Object >> #at: & Co. are recursive! :-)

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Thiede, Christoph
Gesendet: Samstag, 11. April 2020 16:32 Uhr
An: Chris Muller; The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 

Hi all! Thank you very much for having this interesting discussion :-)


@Chris:

> > -1. :-) Warnings are Notifications,

> As are Errors.  Right?

Nope, sorry ;-)
 

The two main use cases of ModificationForbidden present opposite perspectives onto it.  For "protection from accidentally modifying a literal in a CompiledMethod", I understand the inclination to make it an Error.  However, for the context of db handling, [#markDirty + #resume] is normal processing, not an "error", and not even exceptional, either, so perhaps this is just a semantic irritation sensitivity on my part.. sorry. 

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:
>    [ myDbApp doStuff ]
>      on: ModificationForbidden
>      do:
>           [ : forbidden |
>           forbidden object beWritableObject.
>           forbidden resumptionValue: forbidden retryModificationNoResume.
>           forbidden resume: forbidden resumptionValue ]
>      on: Error
>      do: [ : err | myDbApp logErrorAndNotifyUser ]

This clarification was very helpful for me. I was not aware of your second use case before.

In my opinion, we are talking about two completely different use cases for the same exception.
Literal protection is a low-level error, comparable to out-of-bounds things and primitive failures. You almost never do want to ignore or fix them.
Write barriers for #markDirty, on the other hand, sound like a domain-specific topic to me that should neither raise an error, nor eventually signal an UnhandledError, but be resumed automatically (unless handled differently) by a #defaultAction that removes the barrier (and additional handlers could, if desired, turn on some cache or so).
I have never dealt with Magma or any other DB framework for Smalltalk, but why do you (or would you) use these VM-based mechanisms for a high-level feature? Without knowing any details about your application, personally I would probably design an own exception (DirtyModification?) for that purpose. This would allow you to clearly distinguish between low-level errors ("whoops, I just made an attempt to change a read-only code literal") and higher-level exceptions (DirtyModification). If we would follow my proposal to raise ModificationForbidden from Object instead of Context, you could also consider to override #modificationForbiddenFor:at:put: in your database objects to raise DirtyModification instead of ModificationForbidden (in the same way as some classes override #error or #primitiveError).

However, focusing again on the literal protection aspect, I still don't see when the current default #resume behavior of ModificationForbidden would be ever helpful. MF >> #resume calls Exception >> #resume: which does nothing more than to return resumptionValue! When do we actually need this resumptionValue?
Why can't we design MF like the following:

#resume - not possible, will signal IllegalResumeAttempt
#retryModification - retries the modification and returns nothing special
#forceModification: - makes the object to modify writable, retries the modification and, optionally, makes the object read-only again

If we don't want to break things (that are somehow wrong according to contemporary notion), we could make it a Warning in the Squeak 5.x release stream and turn it into an error with Squeak 6.0. That is: make it an Error today in Trunk, but if we would create a 5.4 release, we would have to remember changing it back... :-/

IIRC ModificationForbidden was introduced in 6.0alpha the first time?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]>
Gesendet: Samstag, 11. April 2020 11:16:00
An: Chris Muller; The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
In this case we might want specialized subclasses...

Le sam. 11 avr. 2020 à 03:45, Chris Muller <[hidden email]> a écrit :
I think so, because if you try to use it for something else, it'll get entangled with your application's standard error handling.  Regular apps have error handling like:

   [ myApp doStuff ] on: Error do: [ : err | myApp logErrorAndNotifyUser ]

and so for the use-case, Protect CompiledMethod Literals from Accidental Modification, inheriting from Error will allow the best backward compatibility with existing handlers.

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:

   [ myDbApp doStuff ]
     on: ModificationForbidden
     do:
          [ : forbidden |
          forbidden object beWritableObject.
          forbidden resumptionValue: forbidden retryModificationNoResume.
          forbidden resume: forbidden resumptionValue ]
     on: Error
     do: [ : err | myDbApp logErrorAndNotifyUser ]

But now that I'm handling ModificationForbidden separately, what if I want Protect CompiledMethod Literals from Accidental Modification, too?  I'm no longer handling correctly for that, because the handler has to assume they're signaled in the context of the DB use case and not the Protection use case.

 - Chris

On Fri, Apr 10, 2020 at 12:06 PM tim Rowledge <[hidden email]> wrote:


> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>
> The two main use cases of ModificationForbidden present opposite perspectives onto it.

In that case perhaps we actually need two different signals?

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Has an inferiority complex, but not a very good one.






Reply | Threaded
Open this post in threaded view
|

Re: Debugger - Proceed button (was: Why is ModificationForbidden not an Error?)

Jakob Reschke-2
Think of this: you may not be able to reasonably proceed after an unresumable error without modifying the system or the context. But the IDE lets you do just that: you can change something on the stack in the debugger, or implement the missing method, then proceed and violà, you just reasonably proceeded from an otherwise unresumable error.

I suppose the methods you mentioned are recursive/repeating to allow for exactly that kind of workflow.

One should naturally be allowed to Proceed from the notifier window of a Halt or Warning.

Which leads us to the topic of exception-specific or context-specific buttons in the notifier once again. I don't remember which topic it was, but I wished for that already once during the last few months. Maybe it was the deprecation warnings and now we have an explanation how to deal with Warnings in the notifier and those text actions that allow to disable the warnings on the spot. And as always I'd like to point out that Common Lisp has a nice concept for responding to exceptions both automatically and interactively, with user-code-registered restart operations that can be invoked from the debugger: http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html In Smalltalk you can already use #return, #retry, #resume etc in an exception handler, but you cannot access the handlers nicely from the debugger, and you cannot "resume somewhere along the way to the exception".

Am Sa., 11. Apr. 2020 um 16:38 Uhr schrieb Thiede, Christoph <[hidden email]>:

Just another thought: I see some confusion around the Proceed button in the debugger, and I felt the same confusion sometimes ago. Please forgive me for the sacrilege, but should we maybe question its general existence?

Depending on the domain, it actually performs a mix of #retry (made possible by the quite confusing recursive implementation of Object >> #at:, Object >> #doesNotUnderstand: and others, I did not yet found any other motivation than the Proceed button to use recursion here) and ignore (#resumeUnchecked:, especially useful for UnhandledWarnings and Halts). Would it be a reasonable goal to eliminate this button in the pre-debugger window and replace it with two buttons, Restart and Ignore? We could hide even hide the restart button if not appropriate (i.e., the exception is not an error).

What do you think?
And it would be great if anyone here could explain why Object >> #at: & Co. are recursive! :-)

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Thiede, Christoph
Gesendet: Samstag, 11. April 2020 16:32 Uhr
An: Chris Muller; The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 

Hi all! Thank you very much for having this interesting discussion :-)


@Chris:

> > -1. :-) Warnings are Notifications,

> As are Errors.  Right?

Nope, sorry ;-)
 

The two main use cases of ModificationForbidden present opposite perspectives onto it.  For "protection from accidentally modifying a literal in a CompiledMethod", I understand the inclination to make it an Error.  However, for the context of db handling, [#markDirty + #resume] is normal processing, not an "error", and not even exceptional, either, so perhaps this is just a semantic irritation sensitivity on my part.. sorry. 

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:
>    [ myDbApp doStuff ]
>      on: ModificationForbidden
>      do:
>           [ : forbidden |
>           forbidden object beWritableObject.
>           forbidden resumptionValue: forbidden retryModificationNoResume.
>           forbidden resume: forbidden resumptionValue ]
>      on: Error
>      do: [ : err | myDbApp logErrorAndNotifyUser ]

This clarification was very helpful for me. I was not aware of your second use case before.

In my opinion, we are talking about two completely different use cases for the same exception.
Literal protection is a low-level error, comparable to out-of-bounds things and primitive failures. You almost never do want to ignore or fix them.
Write barriers for #markDirty, on the other hand, sound like a domain-specific topic to me that should neither raise an error, nor eventually signal an UnhandledError, but be resumed automatically (unless handled differently) by a #defaultAction that removes the barrier (and additional handlers could, if desired, turn on some cache or so).
I have never dealt with Magma or any other DB framework for Smalltalk, but why do you (or would you) use these VM-based mechanisms for a high-level feature? Without knowing any details about your application, personally I would probably design an own exception (DirtyModification?) for that purpose. This would allow you to clearly distinguish between low-level errors ("whoops, I just made an attempt to change a read-only code literal") and higher-level exceptions (DirtyModification). If we would follow my proposal to raise ModificationForbidden from Object instead of Context, you could also consider to override #modificationForbiddenFor:at:put: in your database objects to raise DirtyModification instead of ModificationForbidden (in the same way as some classes override #error or #primitiveError).

However, focusing again on the literal protection aspect, I still don't see when the current default #resume behavior of ModificationForbidden would be ever helpful. MF >> #resume calls Exception >> #resume: which does nothing more than to return resumptionValue! When do we actually need this resumptionValue?
Why can't we design MF like the following:

#resume - not possible, will signal IllegalResumeAttempt
#retryModification - retries the modification and returns nothing special
#forceModification: - makes the object to modify writable, retries the modification and, optionally, makes the object read-only again

If we don't want to break things (that are somehow wrong according to contemporary notion), we could make it a Warning in the Squeak 5.x release stream and turn it into an error with Squeak 6.0. That is: make it an Error today in Trunk, but if we would create a 5.4 release, we would have to remember changing it back... :-/

IIRC ModificationForbidden was introduced in 6.0alpha the first time?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]>
Gesendet: Samstag, 11. April 2020 11:16:00
An: Chris Muller; The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
 
In this case we might want specialized subclasses...

Le sam. 11 avr. 2020 à 03:45, Chris Muller <[hidden email]> a écrit :
I think so, because if you try to use it for something else, it'll get entangled with your application's standard error handling.  Regular apps have error handling like:

   [ myApp doStuff ] on: Error do: [ : err | myApp logErrorAndNotifyUser ]

and so for the use-case, Protect CompiledMethod Literals from Accidental Modification, inheriting from Error will allow the best backward compatibility with existing handlers.

But if they want to use ModificationForbidden for a Write Barrier, they'll probably want to extricate it from Error in the handler:

   [ myDbApp doStuff ]
     on: ModificationForbidden
     do:
          [ : forbidden |
          forbidden object beWritableObject.
          forbidden resumptionValue: forbidden retryModificationNoResume.
          forbidden resume: forbidden resumptionValue ]
     on: Error
     do: [ : err | myDbApp logErrorAndNotifyUser ]

But now that I'm handling ModificationForbidden separately, what if I want Protect CompiledMethod Literals from Accidental Modification, too?  I'm no longer handling correctly for that, because the handler has to assume they're signaled in the context of the DB use case and not the Protection use case.

 - Chris

On Fri, Apr 10, 2020 at 12:06 PM tim Rowledge <[hidden email]> wrote:


> On 2020-04-09, at 6:55 PM, Chris Muller <[hidden email]> wrote:
>
> The two main use cases of ModificationForbidden present opposite perspectives onto it.

In that case perhaps we actually need two different signals?

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Has an inferiority complex, but not a very good one.







123