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:
* http://forum.world.st/Squeak-s-AssertionFailure-vs-SUnit-s-TestFailure-td510... * 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
Hi Christoph,
On Apr 9, 2020, at 7:01 AM, Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de 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-td510... 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
Making it an error might also make smalltalkCI (through SUnit) catch it to continue. Failing the tests rather than halting the run.
Eliot Miranda eliot.miranda@gmail.com schrieb am Do., 9. Apr. 2020, 17:04:
Hi Christoph,
On Apr 9, 2020, at 7:01 AM, Thiede, Christoph < Christoph.Thiede@student.hpi.uni-potsdam.de> 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-td510...
http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-tp5113273p5113433.html
Best, Christoph
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 <eliot.miranda@gmail.commailto:eliot.miranda@gmail.com> schrieb am Do., 9. Apr. 2020, 17:04: Hi Christoph,
On Apr 9, 2020, at 7:01 AM, Thiede, Christoph <Christoph.Thiede@student.hpi.uni-potsdam.demailto:Christoph.Thiede@student.hpi.uni-potsdam.de> 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-td510...https://urldefense.proofpoint.com/v2/url?u=http-3A__forum.world.st_Squeak-2Ds-2DAssertionFailure-2Dvs-2DSUnit-2Ds-2DTestFailure-2Dtd5106818.html&d=DwMFaQ&c=59WElTcIEwbBjXQe6gMr9RyqhrzJYRWAhv5h0b8rPQw&r=kLkLKHssG2E-0CCrQK0G4ZYfmhf4xgJ5Z4-lug5DUv8&m=GiL_MDFq8_1Q6uMVdFUlklG5DS-pUNURkQYNhqBuwsU&s=flha9x8Pmp-f2XQJ75NCtbmlvFMJ8BVxW9EWZXeCWNU&e= * http://forum.world.st/The-Trunk-Kernel-eem-1294-mcz-td5112196.htmlhttps://urldefense.proofpoint.com/v2/url?u=http-3A__forum.world.st_The-2DTrunk-2DKernel-2Deem-2D1294-2Dmcz-2Dtd5112196.html&d=DwMFaQ&c=59WElTcIEwbBjXQe6gMr9RyqhrzJYRWAhv5h0b8rPQw&r=kLkLKHssG2E-0CCrQK0G4ZYfmhf4xgJ5Z4-lug5DUv8&m=GiL_MDFq8_1Q6uMVdFUlklG5DS-pUNURkQYNhqBuwsU&s=G8LZqapZe45_LYXWp0wKEVCqLqfZvI3L4H38orfJcwY&e= * http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-tp5113273p5113433.htmlhttps://urldefense.proofpoint.com/v2/url?u=http-3A__forum.world.st_The-2DTrunk-2DKernel-2Deem-2D1317-2Dmcz-2Dtp5113273p5113433.html&d=DwMFaQ&c=59WElTcIEwbBjXQe6gMr9RyqhrzJYRWAhv5h0b8rPQw&r=kLkLKHssG2E-0CCrQK0G4ZYfmhf4xgJ5Z4-lug5DUv8&m=GiL_MDFq8_1Q6uMVdFUlklG5DS-pUNURkQYNhqBuwsU&s=yFmOvGnXlNaAV4MacZmmg2eUUBAPdHCeoYwSsYISYpw&e=
Best, Christoph
********************************************************************** 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.
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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Eliot Miranda eliot.miranda@gmail.com 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 Christoph.Thiede@student.hpi.uni-potsdam.de 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-td510... * 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
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 < Christoph.Thiede@student.hpi.uni-potsdam.de> wrote:
Thanks for the fast feedback, I am going to commit this to the Inbox! http://www.hpi.de/
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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Eliot Miranda eliot.miranda@gmail.com *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 < Christoph.Thiede@student.hpi.uni-potsdam.de> 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-td510...
http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-tp5113273p5113433.html
Best, Christoph
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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Chris Muller asqueaker@gmail.com 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 <Christoph.Thiede@student.hpi.uni-potsdam.demailto:Christoph.Thiede@student.hpi.uni-potsdam.de> 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 <squeak-dev-bounces@lists.squeakfoundation.orgmailto:squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Eliot Miranda <eliot.miranda@gmail.commailto:eliot.miranda@gmail.com> 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 <Christoph.Thiede@student.hpi.uni-potsdam.demailto:Christoph.Thiede@student.hpi.uni-potsdam.de> 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-td510... * 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
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
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 ma.chris.m@gmail.com 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
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
On Apr 10, 2020, at 10:06 AM, tim Rowledge tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
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 tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
In this case we might want specialized subclasses...
Le sam. 11 avr. 2020 à 03:45, Chris Muller asqueaker@gmail.com 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 tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
Hi all! Thank you very much for having this interesting discussion :-)
@Chris:
-1. :-) Warnings are Notifications,
As are Errors. Right?
Nope, sorry ;-) [cid:1a371365-7210-4ea3-a6da-6dfbd89c6b54] [cid:1000a733-fc69-4ba3-bae8-c3cf25021584]
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 proposalhttp://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com 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 <asqueaker@gmail.commailto:asqueaker@gmail.com> 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 <tim@rowledge.orgmailto:tim@rowledge.org> wrote:
On 2020-04-09, at 6:55 PM, Chris Muller <asqueaker@gmail.commailto:asqueaker@gmail.com> 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; tim@rowledge.orgmailto:tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
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 confusinghttp://forum.world.st/I-broke-the-debugger-td5110752.html#a5112307#:~:text=recursively 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). http://www.hpi.de/
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 squeak-dev-bounces@lists.squeakfoundation.org 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 ;-) [cid:1a371365-7210-4ea3-a6da-6dfbd89c6b54] [cid:1000a733-fc69-4ba3-bae8-c3cf25021584]
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 proposalhttp://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com 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 <asqueaker@gmail.commailto:asqueaker@gmail.com> 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 <tim@rowledge.orgmailto:tim@rowledge.org> wrote:
On 2020-04-09, at 6:55 PM, Chris Muller <asqueaker@gmail.commailto:asqueaker@gmail.com> 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; tim@rowledge.orgmailto:tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
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-res... 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 < Christoph.Thiede@student.hpi.uni-potsdam.de>:
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 http://forum.world.st/I-broke-the-debugger-td5110752.html#a5112307%23:~:text=recursively 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). http://www.hpi.de/
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 squeak-dev-bounces@lists.squeakfoundation.org 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 http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com *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 asqueaker@gmail.com 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 tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
Interesting: the Orange Book on p. 396 states that if you press proceed in the full debugger, the result of the interrupted message send is assumed to be the result of the last expression that you evaluated (e. g. via print it) in the debugger. Or nil if you did not evaluate anything.
Seems to be no longer the case though. Also we have "return entered value" now.
Am Sa., 11. Apr. 2020 um 21:13 Uhr schrieb Jakob Reschke < forums.jakob@resfarm.de>:
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-res... 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 < Christoph.Thiede@student.hpi.uni-potsdam.de>:
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 http://forum.world.st/I-broke-the-debugger-td5110752.html#a5112307%23:~:text=recursively 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). http://www.hpi.de/
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 squeak-dev-bounces@lists.squeakfoundation.org 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 http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com *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 asqueaker@gmail.com 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 tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
On Apr 11, 2020, at 12:13 PM, Jakob Reschke forums.jakob@resfarm.de wrote:
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-res... 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".
*1. Good points. Good analysis.
Am Sa., 11. Apr. 2020 um 16:38 Uhr schrieb Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de: 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 squeak-dev-bounces@lists.squeakfoundation.org 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 ;-) <pastedImage.png>
<pastedImage.png>
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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com 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 asqueaker@gmail.com 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 tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
Warnings are Notifications
Here is a related discussion about that: http://forum.world.st/Discussion-Warning-vs-Halt-or-quot-Why-is-a-warning-a-... [http://forum.world.st/Discussion-Warning-vs-Halt-or-quot-Why-is-a-warning-a-...]
Best, Marcel Am 11.04.2020 16:32:56 schrieb Thiede, Christoph christoph.thiede@student.hpi.uni-potsdam.de: 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 [http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433%... 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com 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 <asqueaker@gmail.com [mailto:asqueaker@gmail.com]> 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 <tim@rowledge.org [mailto:tim@rowledge.org]> wrote:
On 2020-04-09, at 6:55 PM, Chris Muller <asqueaker@gmail.com [mailto:asqueaker@gmail.com]> 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; tim@rowledge.org [mailto:tim@rowledge.org]; http://www.rowledge.org/tim [http://www.rowledge.org/tim] Useful random insult:- Has an inferiority complex, but not a very good one.
Hi Christoph,
On Sat, Apr 11, 2020 at 7:32 AM Thiede, Christoph < Christoph.Thiede@student.hpi.uni-potsdam.de> wrote:
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.
There are many use cases for the same exception, just as there are many use cases for bounds violations or divide by zero, or, or, .... The point is that at the point where the exception is raised neither the VM nor the code immediately above it knows what the use case is, and the exception is raised precisely to find out how the exception should be handled, which means that sears hing for the exception/.handling the exception is about discovering what the particular use case *is*. Sio no, one can't magically intuit what the high level use case is at the point of failure. That's *why* we have exception systems.
*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 http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Nicolas Cellier nicolas.cellier.aka.nice@gmail.com *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 asqueaker@gmail.com 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 tim@rowledge.org wrote:
On 2020-04-09, at 6:55 PM, Chris Muller asqueaker@gmail.com 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; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Has an inferiority complex, but not a very good one.
Hi all!
So, we make ModificationForbidden a (resumable) Error for now? Is this the conclusion? Is there already a change in the inbox for this?
---
Side note: From its current behavior. ModificationForbidden should specialize Warning. But then we really should consider updating TestCase >> timeOut:after: to also catch Warning.
Best, Marcel Am 21.04.2020 06:05:10 schrieb Eliot Miranda eliot.miranda@gmail.com: Hi Christoph,
On Sat, Apr 11, 2020 at 7:32 AM Thiede, Christoph <Christoph.Thiede@student.hpi.uni-potsdam.de [mailto:Christoph.Thiede@student.hpi.uni-potsdam.de]> wrote:
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.
There are many use cases for the same exception, just as there are many use cases for bounds violations or divide by zero, or, or, .... The point is that at the point where the exception is raised neither the VM nor the code immediately above it knows what the use case is, and the exception is raised precisely to find out how the exception should be handled, which means that sears hing for the exception/.handling the exception is about discovering what the particular use case *is*. Sio no, one can't magically intuit what the high level use case is at the point of failure. That's *why* we have exception systems.
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 [http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-td5113273.html#a5113433%... 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 <squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org]> im Auftrag von Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com [mailto:nicolas.cellier.aka.nice@gmail.com]> 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 <asqueaker@gmail.com [mailto:asqueaker@gmail.com]> 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 <tim@rowledge.org [mailto:tim@rowledge.org]> wrote:
On 2020-04-09, at 6:55 PM, Chris Muller <asqueaker@gmail.com [mailto:asqueaker@gmail.com]> 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; tim@rowledge.org [mailto:tim@rowledge.org]; http://www.rowledge.org/tim [http://www.rowledge.org/tim] Useful random insult:- Has an inferiority complex, but not a very good one.
--
_,,,^..^,,,_
best, Eliot
On 2020-04-22, at 3:20 AM, Marcel Taeumel marcel.taeumel@hpi.de wrote:
Hi all!
So, we make ModificationForbidden a (resumable) Error for now? Is this the conclusion?
It's a super-low-level error that ought to be handled really really closely to where the error was raised. As Eliot mentioned, the VM can't know the circumstances and just raises it; the the closest possible handler should be in place that *does* know the circumstances. That way Chris gets to spot that is it a database issue and handle things properly, including likely raising a new error for higher level code.
Given having a handler really close to the source, perhaps we are better off keeping it non-resumable and using one of the other approaches to continuing like #retryUsing: (ExceptionTester>>#simpleRetryUsingTest is the only example in the clean image) ?
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BFM: Branch on Full Moon
Hi All,
On Wed, Apr 22, 2020 at 10:59 AM tim Rowledge tim@rowledge.org wrote:
On 2020-04-22, at 3:20 AM, Marcel Taeumel marcel.taeumel@hpi.de wrote:
Hi all!
So, we make ModificationForbidden a (resumable) Error for now? Is this
the conclusion?
Yes, I hope so :-)
It's a super-low-level error that ought to be handled really really closely to where the error was raised. As Eliot mentioned, the VM can't know the circumstances and just raises it; the the closest possible handler should be in place that *does* know the circumstances. That way Chris gets to spot that is it a database issue and handle things properly, including likely raising a new error for higher level code.
As I've already mentioned what one can do, and the VisualWorks version does do, for GemStone-style persistence, as add behavior to the exception so one can specify a per-object response.
So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different clients to map the exception into different responses as desired. So can we please stop wasting time discussing this and get on with implementing it? The GemStone folks have understood how to manage ModificationForbidden for years and the use of it has been in production. We simply need to catch up. We're nearly there.
Please don't make me explain this idea once again ;-)
Given having a handler really close to the source, perhaps we are better
off keeping it non-resumable and using one of the other approaches to continuing like #retryUsing: (ExceptionTester>>#simpleRetryUsingTest is the only example in the clean image) ?
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BFM: Branch on Full Moon
Hi Eliot.
Please find attached a change set. Like this? Here are some examples:
array := #(1 2 3).
ModificationForbidden for: array send: #showln: to: Transcript.
ModificationForbidden for: array send: (MessageSend receiver: Transcript selector: #showln:).
"Try out." array at: 1 put: #foo.
Best, Marcel Am 23.04.2020 01:50:42 schrieb Eliot Miranda eliot.miranda@gmail.com: Hi All,
On Wed, Apr 22, 2020 at 10:59 AM tim Rowledge <tim@rowledge.org [mailto:tim@rowledge.org]> wrote:
On 2020-04-22, at 3:20 AM, Marcel Taeumel <marcel.taeumel@hpi.de [mailto:marcel.taeumel@hpi.de]> wrote:
Hi all!
So, we make ModificationForbidden a (resumable) Error for now? Is this the conclusion?
Yes, I hope so :-)
It's a super-low-level error that ought to be handled really really closely to where the error was raised. As Eliot mentioned, the VM can't know the circumstances and just raises it; the the closest possible handler should be in place that *does* know the circumstances. That way Chris gets to spot that is it a database issue and handle things properly, including likely raising a new error for higher level code.
As I've already mentioned what one can do, and the VisualWorks version does do, for GemStone-style persistence, as add behavior to the exception so one can specify a per-object response.
So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different clients to map the exception into different responses as desired. So can we please stop wasting time discussing this and get on with implementing it? The GemStone folks have understood how to manage ModificationForbidden for years and the use of it has been in production. We simply need to catch up. We're nearly there.
Please don't make me explain this idea once again ;-)
Given having a handler really close to the source, perhaps we are better off keeping it non-resumable and using one of the other approaches to continuing like #retryUsing: (ExceptionTester>>#simpleRetryUsingTest is the only example in the clean image) ?
tim -- tim Rowledge; tim@rowledge.org [mailto:tim@rowledge.org]; http://www.rowledge.org/tim [http://www.rowledge.org/tim] Strange OpCodes: BFM: Branch on Full Moon
--
_,,,^..^,,,_
best, Eliot
Hi Marcel,
On Thu, Apr 23, 2020 at 3:15 AM Marcel Taeumel marcel.taeumel@hpi.de wrote:
Hi Eliot.
Please find attached a change set. Like this? Here are some examples:
array := #(1 2 3).
ModificationForbidden for: array send: #showln: to: Transcript.
ModificationForbidden for: array send: (MessageSend receiver: Transcript selector: #showln:).
"Try out." array at: 1 put: #foo.
Yes, this looks good. Exactly the kind of thing. The only issue now is what is a convenient signature for the message send in ManagedObjects. We should consult with the GemSTone folks and perhaps look at the VisualWorks code. I'm cc'ing Martin McClure for comment.
Best,
Marcel
Am 23.04.2020 01:50:42 schrieb Eliot Miranda eliot.miranda@gmail.com: Hi All,
On Wed, Apr 22, 2020 at 10:59 AM tim Rowledge tim@rowledge.org wrote:
On 2020-04-22, at 3:20 AM, Marcel Taeumel marcel.taeumel@hpi.de
wrote:
Hi all!
So, we make ModificationForbidden a (resumable) Error for now? Is this
the conclusion?
Yes, I hope so :-)
It's a super-low-level error that ought to be handled really really closely to where the error was raised. As Eliot mentioned, the VM can't know the circumstances and just raises it; the the closest possible handler should be in place that *does* know the circumstances. That way Chris gets to spot that is it a database issue and handle things properly, including likely raising a new error for higher level code.
As I've already mentioned what one can do, and the VisualWorks version does do, for GemStone-style persistence, as add behavior to the exception so one can specify a per-object response.
So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different clients to map the exception into different responses as desired. So can we please stop wasting time discussing this and get on with implementing it? The GemStone folks have understood how to manage ModificationForbidden for years and the use of it has been in production. We simply need to catch up. We're nearly there.
Please don't make me explain this idea once again ;-)
Given having a handler really close to the source, perhaps we are better
off keeping it non-resumable and using one of the other approaches to continuing like #retryUsing: (ExceptionTester>>#simpleRetryUsingTest is the only example in the clean image) ?
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BFM: Branch on Full Moon
_,,,^..^,,,_ best, Eliot
_,,,^..^,,,_
best, Eliot
Hi Eliot,
Thanks for your patience with our questions while we get up to speed understanding how to use this new feature.
It's a super-low-level error that ought to be handled really really
closely to where the error was raised. As Eliot mentioned, the VM can't know the circumstances and just raises it; the the closest possible handler should be in place that *does* know the circumstances. That way Chris gets to spot that is it a database issue and handle things properly, including likely raising a new error for higher level code.
As I've already mentioned what one can do, and the VisualWorks version does do, for GemStone-style persistence, as add behavior to the exception so one can specify a per-object response.
So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different
clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
- Chris
So can we please stop wasting time discussing this and get on with implementing it? The GemStone folks have understood how to manage ModificationForbidden for years and the use of it has been in production. We simply need to catch up. We're nearly there.
Please don't make me explain this idea once again ;-)
Given having a handler really close to the source, perhaps we are better
off keeping it non-resumable and using one of the other approaches to continuing like #retryUsing: (ExceptionTester>>#simpleRetryUsingTest is the only example in the clean image) ?
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BFM: Branch on Full Moon
-- _,,,^..^,,,_ best, Eliot
On Apr 23, 2020, at 5:55 PM, Chris Muller asqueaker@gmail.com wrote:
Hi Eliot,
Thanks for your patience with our questions while we get up to speed understanding how to use this new feature.
It's a super-low-level error that ought to be handled really really closely to where the error was raised. As Eliot mentioned, the VM can't know the circumstances and just raises it; the the closest possible handler should be in place that *does* know the circumstances. That way Chris gets to spot that is it a database issue and handle things properly, including likely raising a new error for higher level code.
As I've already mentioned what one can do, and the VisualWorks version does do, for GemStone-style persistence, as add behavior to the exception so one can specify a per-object response.
So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified. So very simply we can have a pluggable solution that allows different clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it. Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
- Chris
So can we please stop wasting time discussing this and get on with implementing it? The GemStone folks have understood how to manage ModificationForbidden for years and the use of it has been in production. We simply need to catch up. We're nearly there.
Please don't make me explain this idea once again ;-)
Given having a handler really close to the source, perhaps we are better off keeping it non-resumable and using one of the other approaches to continuing like #retryUsing: (ExceptionTester>>#simpleRetryUsingTest is the only example in the clean image) ?
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BFM: Branch on Full Moon
-- _,,,^..^,,,_ best, Eliot
So if the exception is unhandled, then before it raises an UnhandledError
it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different
clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something?
Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
Best, Marcel Am 24.04.2020 05:26:56 schrieb Chris Muller ma.chris.m@gmail.com: So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified. So very simply we can have a pluggable solution that allows different clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something? Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
On 2020-04-24, at 3:10 AM, Marcel Taeumel marcel.taeumel@hpi.de wrote:
But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
The fact that there is a helpful default handler for an exception does not (should not!) mean you can't catch it and do something more to your liking
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Design simplicity: It was developed on a shoe-string budget.
On Apr 24, 2020, at 9:55 AM, tim Rowledge tim@rowledge.org wrote:
On 2020-04-24, at 3:10 AM, Marcel Taeumel marcel.taeumel@hpi.de wrote:
But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
The fact that there is a helpful default handler for an exception does not (should not!) mean you can't catch it and do something more to your liking
+1.
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Design simplicity: It was developed on a shoe-string budget.
The fact that there is a helpful default handler for an exception does not (should not!) mean you can't catch it and do something more to your liking
Only if you control the code. For Magma-like transparency, it must be able to operate on oblivious objects which have ZERO knowledge of any database or handlers. Cmd+s in an Inspector should be picked up and saved in the next DB commit, unless it's a CM-literal, in which case it should error immediately...
Am Fr., 24. Apr. 2020 um 23:56 Uhr schrieb Chris Muller asqueaker@gmail.com:
The fact that there is a helpful default handler for an exception does not (should not!) mean you can't catch it and do something more to your liking
Only if you control the code. For Magma-like transparency, it must be able to operate on oblivious objects which have ZERO knowledge of any database or handlers. Cmd+s in an Inspector should be picked up and saved in the next DB commit, unless it's a CM-literal, in which case it should error immediately...
Hmm for this particular case I don't see the issue. Modification through an inspector will create references to other objects, so to run into ModificationForbidden here, you would have to modify a composite literal object, which could only be an Array if I am not mistaken. The elements of literal arrays are literals themselves (not in the CompiledMethod-sense, but they are all immutable now, right? think of nested arrays). So when you press Cmd+s, you will immediately get the exception, before anything changes in the object. So the database would not be affected by the error or the modification attempt, right?
Or it would proceed immediately because it was registered so in the object-specific handler supplied via the methods in Marcel's changeset. Then things get modified and so they would be in the database. Do you mean the exception could arise again in the database code?
I finally got around to read Marcel's changeset and the code that signals ModificationForbidden. Now I see that resuming the ModificationForbidden means to skip the modification and proceed with the code ahead, not to do the modification despite the read-only state as I assumed. Sorry.
Let me check my understanding. If there is a forbidden modification, the only way to abort an operation via object handlers is to do a non-local return eventually (handler is a block or signals another exception). Because the defaultAction implies that the ModificationForbidden exception will be resumed and you can only control the resumption value, unless there is a non-local return eventually. Is that correct? Then I'm thinking one would rather choose to handle ModificationForbidden conventionally with on:do: if one wishes to abort something. And use object handlers only for use cases where you can actually do something about it.
In that case I'm wondering how an object database is actually going to proceed from there. Copy, modify, record, become:, let resume? If the answer is too long, just tell me I would have to read it up in the literature. ;-)
Am Sa., 25. Apr. 2020 um 10:06 Uhr schrieb Jakob Reschke forums.jakob@resfarm.de:
Am Fr., 24. Apr. 2020 um 23:56 Uhr schrieb Chris Muller asqueaker@gmail.com:
The fact that there is a helpful default handler for an exception does not (should not!) mean you can't catch it and do something more to your liking
Only if you control the code. For Magma-like transparency, it must be able to operate on oblivious objects which have ZERO knowledge of any database or handlers. Cmd+s in an Inspector should be picked up and saved in the next DB commit, unless it's a CM-literal, in which case it should error immediately...
Hmm for this particular case I don't see the issue. Modification through an inspector will create references to other objects, so to run into ModificationForbidden here, you would have to modify a composite literal object, which could only be an Array if I am not mistaken. The elements of literal arrays are literals themselves (not in the CompiledMethod-sense, but they are all immutable now, right? think of nested arrays). So when you press Cmd+s, you will immediately get the exception, before anything changes in the object. So the database would not be affected by the error or the modification attempt, right?
Or it would proceed immediately because it was registered so in the object-specific handler supplied via the methods in Marcel's changeset. Then things get modified and so they would be in the database. Do you mean the exception could arise again in the database code?
On Sat, Apr 25, 2020 at 3:06 AM Jakob Reschke forums.jakob@resfarm.de wrote:
Am Fr., 24. Apr. 2020 um 23:56 Uhr schrieb Chris Muller < asqueaker@gmail.com>:
The fact that there is a helpful default handler for an exception does
not (should not!) mean you can't catch it and do something more to your liking
Only if you control the code. For Magma-like transparency, it must be
able to operate on oblivious objects which have ZERO knowledge of any database or handlers. Cmd+s in an Inspector should be picked up and saved in the next DB commit, unless it's a CM-literal, in which case it should error immediately...
Hmm for this particular case I don't see the issue. Modification through an inspector will create references to other objects, so to run into ModificationForbidden here, you would have to modify a composite literal object, which could only be an Array if I am not mistaken.
Correct. And, the Inspector code doesn't know whether its a CM-literal or just a regular, should-be-updatable Array. It'll either be registered with a handler, or it won't.
The elements of literal arrays are literals themselves (not in the CompiledMethod-sense, but they are all immutable now, right? think of nested arrays).
No. From my understanding only the root Array is immutable, the nested ones aren't. This isn't related to the issue being raised, just answering your question..
So when you press Cmd+s, you will immediately get the exception, before anything changes in the object. So the database would not be affected by the error or the modification attempt, right?
Or it would proceed immediately because it was registered so in the object-specific handler supplied via the methods in Marcel's changeset. Then things get modified and so they would be in the database. Do you mean the exception could arise again in the database code?
The above is what I'm trying figure out. My understanding is, if you registered a handler for the object, it'll run that, otherwise the defaultAction which is to open a debugger saying ModificationForbidden.
The challenge, at least from the way Magma is implemented, is at the point where it's time to register an Array with ManagedObjects, there's no way to know whether it's a CM-literal or not. But even that is independent of the fact the read-only bit is still exposed for modification by other use-cases. In a coordinated, frozen system like a GemStone business app, this can be managed. In a live system that might make use of dynamically loaded modules, it could be dangerous.
- Chris
Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
From what I can see, the only problem with my proposal that resists still in
the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede < christoph.thiede@student.hpi.uni-potsdam.de> wrote:
Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
From what I can see, the only problem with my proposal that resists still in the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
Alright, anyone having any new opinion about this? Let's make a decision! :-)
Best,
Christoph
http://www.hpi.de/ ________________________________ Von: Chris Muller asqueaker@gmail.com Gesendet: Donnerstag, 24. September 2020 21:33:27 An: The general-purpose Squeak developers list; Thiede, Christoph Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede <christoph.thiede@student.hpi.uni-potsdam.demailto:christoph.thiede@student.hpi.uni-potsdam.de> wrote: Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
From what I can see, the only problem with my proposal that resists still in
the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On Sep 30, 2020, at 3:48 AM, Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de wrote:
Alright, anyone having any new opinion about this? Let's make a decision! :-)
I don’t see how it can be other than an error. If one attempts to modify a literal that is an error. If one attempts to modify a read-only object then that is an error, unless some smart system is overloading read-only-ness to implement a read barrier.
Best,
Christoph
Von: Chris Muller asqueaker@gmail.com Gesendet: Donnerstag, 24. September 2020 21:33:27 An: The general-purpose Squeak developers list; Thiede, Christoph Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede christoph.thiede@student.hpi.uni-potsdam.de wrote: Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
This makes no sense to me. Test runners collect tests that error just as they collect tests that assert fail. Why would a ModificationForbidden Another be considered an error?
From what I can see, the only problem with my proposal that resists still in the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
I don’t want yo build something that is incompatible with gemstone. Currently we don’t have their attention; Ogaro had thrrr attention. So we have to do the work of ensuring that ModificationForbidden supports the Gemstone use case; it’s a very very important one. on:do: is completely inadequate for this. One needs a system wide exception handler where any ModificationForbidden is routed through a manager that is able to identify that the object in question is in fact being mapped to a database (or a remote system, or a breakout ring system etc). But on:do: handlers are for specific flows of control (currently within a single thread) and cannot serve as system wide handlers.
Here’s a simplified use case. The programmer wants to be able to trace wherever in the system an object is modified. It may occur in arbitrary processes, not just in the current flow of control. To do this efficiently the programmer uses ModificationForbidden to catch a modification, log it, make the object readable, effect the modification, make the object read-only again and proceed. This *cannot* be done with an on:do: handler.
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
I am not involved in this discussion, but if I understand the conversation there is no longer any disagreement about what needs to be done, so we just need to make it happen in trunk. I think there was an inbox submission a while back that could be merged.
+1000 for bringing this issue to a resolution, and thanks Christoph for moving it forward.
Dave
On Wed, Sep 30, 2020 at 05:43:57AM -0700, Eliot Miranda wrote:
On Sep 30, 2020, at 3:48 AM, Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de wrote:
??? Alright, anyone having any new opinion about this? Let's make a decision! :-)
I don???t see how it can be other than an error. If one attempts to modify a literal that is an error. If one attempts to modify a read-only object then that is an error, unless some smart system is overloading read-only-ness to implement a read barrier.
Best,
Christoph
Von: Chris Muller asqueaker@gmail.com Gesendet: Donnerstag, 24. September 2020 21:33:27 An: The general-purpose Squeak developers list; Thiede, Christoph Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede christoph.thiede@student.hpi.uni-potsdam.de wrote: Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
This makes no sense to me. Test runners collect tests that error just as they collect tests that assert fail. Why would a ModificationForbidden Another be considered an error?
From what I can see, the only problem with my proposal that resists still in the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
I don???t want yo build something that is incompatible with gemstone. Currently we don???t have their attention; Ogaro had thrrr attention. So we have to do the work of ensuring that ModificationForbidden supports the Gemstone use case; it???s a very very important one. on:do: is completely inadequate for this. One needs a system wide exception handler where any ModificationForbidden is routed through a manager that is able to identify that the object in question is in fact being mapped to a database (or a remote system, or a breakout ring system etc). But on:do: handlers are for specific flows of control (currently within a single thread) and cannot serve as system wide handlers.
Here???s a simplified use case. The programmer wants to be able to trace wherever in the system an object is modified. It may occur in arbitrary processes, not just in the current flow of control. To do this efficiently the programmer uses ModificationForbidden to catch a modification, log it, make the object readable, effect the modification, make the object read-only again and proceed. This *cannot* be done with an on:do: handler.
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
I think there was an inbox submission a while back that could be merged.
Here it is: Kernel-ct.1321http://forum.world.st/The-Inbox-Kernel-ct-1321-mcz-td5114734.html 😊
Best,
Christoph
________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von David T. Lewis lewis@mail.msen.com Gesendet: Mittwoch, 30. September 2020 19:26:30 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
I am not involved in this discussion, but if I understand the conversation there is no longer any disagreement about what needs to be done, so we just need to make it happen in trunk. I think there was an inbox submission a while back that could be merged.
+1000 for bringing this issue to a resolution, and thanks Christoph for moving it forward.
Dave
On Wed, Sep 30, 2020 at 05:43:57AM -0700, Eliot Miranda wrote:
On Sep 30, 2020, at 3:48 AM, Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de wrote:
??? Alright, anyone having any new opinion about this? Let's make a decision! :-)
I don???t see how it can be other than an error. If one attempts to modify a literal that is an error. If one attempts to modify a read-only object then that is an error, unless some smart system is overloading read-only-ness to implement a read barrier.
Best,
Christoph
Von: Chris Muller asqueaker@gmail.com Gesendet: Donnerstag, 24. September 2020 21:33:27 An: The general-purpose Squeak developers list; Thiede, Christoph Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede christoph.thiede@student.hpi.uni-potsdam.de wrote: Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
This makes no sense to me. Test runners collect tests that error just as they collect tests that assert fail. Why would a ModificationForbidden Another be considered an error?
From what I can see, the only problem with my proposal that resists still in the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
I don???t want yo build something that is incompatible with gemstone. Currently we don???t have their attention; Ogaro had thrrr attention. So we have to do the work of ensuring that ModificationForbidden supports the Gemstone use case; it???s a very very important one. on:do: is completely inadequate for this. One needs a system wide exception handler where any ModificationForbidden is routed through a manager that is able to identify that the object in question is in fact being mapped to a database (or a remote system, or a breakout ring system etc). But on:do: handlers are for specific flows of control (currently within a single thread) and cannot serve as system wide handlers.
Here???s a simplified use case. The programmer wants to be able to trace wherever in the system an object is modified. It may occur in arbitrary processes, not just in the current flow of control. To do this efficiently the programmer uses ModificationForbidden to catch a modification, log it, make the object readable, effect the modification, make the object read-only again and proceed. This *cannot* be done with an on:do: handler.
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
Changing the subject line to ask the question directly.
Can Kernel-ct.1321 be merged into trunk now?
See below and prior discussions.
Thanks, Dave
On Wed, Sep 30, 2020 at 05:29:43PM +0000, Thiede, Christoph wrote:
I think there was an inbox submission a while back that could be merged.
Here it is: Kernel-ct.1321http://forum.world.st/The-Inbox-Kernel-ct-1321-mcz-td5114734.html ????
Best,
Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von David T. Lewis lewis@mail.msen.com Gesendet: Mittwoch, 30. September 2020 19:26:30 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
I am not involved in this discussion, but if I understand the conversation there is no longer any disagreement about what needs to be done, so we just need to make it happen in trunk. I think there was an inbox submission a while back that could be merged.
+1000 for bringing this issue to a resolution, and thanks Christoph for moving it forward.
Dave
On Wed, Sep 30, 2020 at 05:43:57AM -0700, Eliot Miranda wrote:
On Sep 30, 2020, at 3:48 AM, Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de wrote:
??? Alright, anyone having any new opinion about this? Let's make a decision! :-)
I don???t see how it can be other than an error. If one attempts to modify a literal that is an error. If one attempts to modify a read-only object then that is an error, unless some smart system is overloading read-only-ness to implement a read barrier.
Best,
Christoph
Von: Chris Muller asqueaker@gmail.com Gesendet: Donnerstag, 24. September 2020 21:33:27 An: The general-purpose Squeak developers list; Thiede, Christoph Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede christoph.thiede@student.hpi.uni-potsdam.de wrote: Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open discussion again. IMO the current situation in the Trunk is still buggy and the last thing we want developers to have to care about. For example, I recently crashed a number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not prepared for ...
This makes no sense to me. Test runners collect tests that error just as they collect tests that assert fail. Why would a ModificationForbidden Another be considered an error?
From what I can see, the only problem with my proposal that resists still in the inbox, Kernel-ct.1321, is related to Chris' Magma implementation. I want to respect this use case (and actually, learning a bit more about Magma is already on my long, long list of nice-to-do stuff), but I have to agree with other people saying that ModificationForbidden is a very low-level error and should not need any special treatment. For this reason, I also think that Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of ManagedObjects in the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that you have reached some kind of feature completeness in your project. Can't we just merge Kernel-ct.1321 for now and resolve this discussion until some new use case arises? For Magma as an external project (still without being familiar at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice to circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could still place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this issue! :-)
I don???t want yo build something that is incompatible with gemstone. Currently we don???t have their attention; Ogaro had thrrr attention. So we have to do the work of ensuring that ModificationForbidden supports the Gemstone use case; it???s a very very important one. on:do: is completely inadequate for this. One needs a system wide exception handler where any ModificationForbidden is routed through a manager that is able to identify that the object in question is in fact being mapped to a database (or a remote system, or a breakout ring system etc). But on:do: handlers are for specific flows of control (currently within a single thread) and cannot serve as system wide handlers.
Here???s a simplified use case. The programmer wants to be able to trace wherever in the system an object is modified. It may occur in arbitrary processes, not just in the current flow of control. To do this efficiently the programmer uses ModificationForbidden to catch a modification, log it, make the object readable, effect the modification, make the object read-only again and proceed. This *cannot* be done with an on:do: handler.
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On Wed, Sep 30, 2020 at 12:59 PM David T. Lewis lewis@mail.msen.com wrote:
Changing the subject line to ask the question directly.
Can Kernel-ct.1321 be merged into trunk now?
I have no objection.
See below and prior discussions.
Thanks, Dave
On Wed, Sep 30, 2020 at 05:29:43PM +0000, Thiede, Christoph wrote:
I think there was an inbox submission a while back that could be
merged.
Here it is: Kernel-ct.1321<
http://forum.world.st/The-Inbox-Kernel-ct-1321-mcz-td5114734.html%3E ????
Best,
Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im
Auftrag von David T. Lewis lewis@mail.msen.com
Gesendet: Mittwoch, 30. September 2020 19:26:30 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
I am not involved in this discussion, but if I understand the
conversation
there is no longer any disagreement about what needs to be done, so we just need to make it happen in trunk. I think there was an inbox
submission
a while back that could be merged.
+1000 for bringing this issue to a resolution, and thanks Christoph for moving it forward.
Dave
On Wed, Sep 30, 2020 at 05:43:57AM -0700, Eliot Miranda wrote:
On Sep 30, 2020, at 3:48 AM, Thiede, Christoph <
Christoph.Thiede@student.hpi.uni-potsdam.de> wrote:
??? Alright, anyone having any new opinion about this? Let's make a
decision! :-)
I don???t see how it can be other than an error. If one attempts to
modify a literal that is an error. If one attempts to modify a read-only object then that is an error, unless some smart system is overloading read-only-ness to implement a read barrier.
Best,
Christoph
Von: Chris Muller asqueaker@gmail.com Gesendet: Donnerstag, 24. September 2020 21:33:27 An: The general-purpose Squeak developers list; Thiede, Christoph Betreff: Re: [squeak-dev] Why is ModificationForbidden not an Error?
Hi Christoph,
Magma does not depend on ModificationForbidden. My participation in
this discussion was merely for my own learning, to try to overcome my skepticism about ModificationForbidden. Changing its superclass shouldn't affect Magma at all. Whether Magma will be able to make use of it is still up in the air. Please feel free to integrate what you and the other folks interested in this decide is best.
Thanks! Chris
On Thu, Sep 24, 2020 at 4:09 AM Christoph Thiede <
christoph.thiede@student.hpi.uni-potsdam.de> wrote:
Hi Chris, hi all,
after months of stagnation, I'd like to bring up this open
discussion again.
IMO the current situation in the Trunk is still buggy and the last
thing we
want developers to have to care about. For example, I recently
crashed a
number of smalltalkCI builds again because some method raised a ModificationForbidden, which the test runner, obviously, was not
prepared
for ...
This makes no sense to me. Test runners collect tests that error just
as they collect tests that assert fail. Why would a ModificationForbidden Another be considered an error?
From what I can see, the only problem with my proposal that resists
still in
the inbox, Kernel-ct.1321, is related to Chris' Magma
implementation. I want
to respect this use case (and actually, learning a bit more about
Magma is
already on my long, long list of nice-to-do stuff), but I have to
agree with
other people saying that ModificationForbidden is a very low-level
error and
should not need any special treatment. For this reason, I also
think that
Marcel's changeset is a bit over-engineered for the Trunk, given the particular fact that we do not have plans for any user of
ManagedObjects in
the Trunk.
Chris, did anything happen on your end regarding the handling of ModificationForbidden in Magma? Iirc you mentioned recently that
you have
reached some kind of feature completeness in your project. Can't we
just
merge Kernel-ct.1321 for now and resolve this discussion until some
new use
case arises? For Magma as an external project (still without being
familiar
at all with its design), I don't understand what would be wrong with handling such exceptions using #on:do:, this would totally suffice
to
circumvent the #defaultAction implementation. If you do not have the possibility to install an exception handler or a ToolSet, you could
still
place an extension override method in ModificationForbidden and (conditionally) inject your custom handling logic there.
What do you think? I would like to finally get ahead with this
issue! :-)
I don???t want yo build something that is incompatible with gemstone.
Currently we don???t have their attention; Ogaro had thrrr attention. So we have to do the work of ensuring that ModificationForbidden supports the Gemstone use case; it???s a very very important one. on:do: is completely inadequate for this. One needs a system wide exception handler where any ModificationForbidden is routed through a manager that is able to identify that the object in question is in fact being mapped to a database (or a remote system, or a breakout ring system etc). But on:do: handlers are for specific flows of control (currently within a single thread) and cannot serve as system wide handlers.
Here???s a simplified use case. The programmer wants to be able to
trace wherever in the system an object is modified. It may occur in arbitrary processes, not just in the current flow of control. To do this efficiently the programmer uses ModificationForbidden to catch a modification, log it, make the object readable, effect the modification, make the object read-only again and proceed. This *cannot* be done with an on:do: handler.
Best, Christoph
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On Thu, Oct 01, 2020 at 11:40:16AM -0700, Eliot Miranda wrote:
On Wed, Sep 30, 2020 at 12:59 PM David T. Lewis lewis@mail.msen.com wrote:
Changing the subject line to ask the question directly.
Can Kernel-ct.1321 be merged into trunk now?
I have no objection.
Done - thanks Christoph.
Dave
Domain and "data storage" layers are intermixed here, hence the trouble with the concept of read-only. If you don't want such a distinction of layers by using different objects in the first place, then I suggest to at least use separate protocols. So yes, use different managers for different kinds of read-onliness. Your domain-specific layer can still delegate to the VM write barrier if that works well. And different applications can still access the same kind/layer of read-onliness, so Eliot's proposal to have one registry for the VM write barrier handling remains valid.
I'd say each domain should also have an own exception class in this case. As an implementation detail, it could inherit from the base ModificationForbidden... or hide the concrete class behind an accessor.
Marcel Taeumel marcel.taeumel@hpi.de schrieb am Fr., 24. Apr. 2020, 12:10:
But this means the DB is now occupying the use of the readOnly bit,
not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
Best, Marcel
Am 24.04.2020 05:26:56 schrieb Chris Muller ma.chris.m@gmail.com:
So if the exception is unhandled, then before it raises an UnhandledError
it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different
clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something?
Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
On Apr 24, 2020, at 9:59 AM, Jakob Reschke forums.jakob@resfarm.de wrote:
Domain and "data storage" layers are intermixed here, hence the trouble with the concept of read-only. If you don't want such a distinction of layers by using different objects in the first place, then I suggest to at least use separate protocols. So yes, use different managers for different kinds of read-onliness. Your domain-specific layer can still delegate to the VM write barrier if that works well. And different applications can still access the same kind/layer of read-onliness, so Eliot's proposal to have one registry for the VM write barrier handling remains valid.
I'd say each domain should also have an own exception class in this case. As an implementation detail, it could inherit from the base ModificationForbidden... or hide the concrete class behind an accessor.
No. That is unnecessary. The issue is to separate intercepting an attempt to write to a read-only object from what happens in response to that attempt. And that’s what the ManagedObjects/defaultAction mechanism does. Attempts to write are caught and other objects handle what happens in response.
Thinking of this issue in the co text of exception handlers doesn’t make sense. Writes happen all over the system, and not necessarily within the dynamic extent of some computation. The exception handler is global. So one won’t be able to establish exception handlers for all cases. Instead, the global exception system dispatches a per-object-specific response through ManagedObjects.
Marcel Taeumel marcel.taeumel@hpi.de schrieb am Fr., 24. Apr. 2020, 12:10:
But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
Best, Marcel
Am 24.04.2020 05:26:56 schrieb Chris Muller ma.chris.m@gmail.com:
So if the exception is unhandled, then before it raises an UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified. So very simply we can have a pluggable solution that allows different clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something?
Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
Hi all,
I'd like to add some color here. I worked with Versant for many many years. This problem bites you so hard you need a tourniquet just to survive it.
Imagine looking at your code and trying to understand why something that looks so simple is completely wrong! You spend a huge amount of time trying to understand why the code doesn't actually do what it SAYS it will do. How is this possible? You read and read, you start writing things down but no it is impossible. You feel like you must be missing something extremely simple or are just losing your mind. Then you decide ok I'll take this step by step and validate every message to see exactly where it breaks. You have been looking at this error for over 72 hours straight because someone is standing over your shoulder waiting to ship the product they promised would be available a week ago.
So you get to a method Integer fortyTwo. And it returns #(0) instead of #(42). What the hell is that!!!! The code says ^#(42)!!!!. You can see it right there!!! Then it hits you. I've been bit by a literal variable change! You add copy and now everything works just like you expected it to. Now you need to get the trounequat because after you kicked the trash can you split your knee on the table. Then you go to talk to your colleague and he falls asleep while you are talking to him and his head hits the keyboard. You ask your boss who looks nearly as bad as the comatose colleague what you should do and he says "Save the code!" So you save the code and roll your colleague under the table so nobody steps on him.
This doesn't happen you think?? Well on Versant you couldn't even change the method if the database was holding onto the litteral! Trying to accept a method gave you a database error!!! Oh great fun that was!
Some people have learned the hard way with litteral blood that copy is essential, and for those that haven't you can save them a lot of pain. Changing litterals without the copy is always wrong especially if it will eventually be stored in a database. Imagine doing direct manipulation on a litteral. Now try to explain what happened since the code never actually changed anything!!! How the hell did that happen!!
Try it yourself and then imagine my barely open eyes trying in vain to understand what happened!
Integer class >> fortyTwo ^#(42)
Integer fortyTwo #(42) Integer fortyTwo at: 1 put: 0. Integer fortyTwo #(0)
Go back and look at the method. Hasn't changed still says ^#(42). Good luck debugging that!
I hope that adds some color around this issue. Ok back to your regularly scheduled program!
All the best,
Ron Teitelbaum
On Fri, Apr 24, 2020 at 1:16 PM Eliot Miranda eliot.miranda@gmail.com wrote:
On Apr 24, 2020, at 9:59 AM, Jakob Reschke forums.jakob@resfarm.de wrote:
Domain and "data storage" layers are intermixed here, hence the trouble with the concept of read-only. If you don't want such a distinction of layers by using different objects in the first place, then I suggest to at least use separate protocols. So yes, use different managers for different kinds of read-onliness. Your domain-specific layer can still delegate to the VM write barrier if that works well. And different applications can still access the same kind/layer of read-onliness, so Eliot's proposal to have one registry for the VM write barrier handling remains valid.
I'd say each domain should also have an own exception class in this case. As an implementation detail, it could inherit from the base ModificationForbidden... or hide the concrete class behind an accessor.
No. That is unnecessary. The issue is to separate intercepting an attempt to write to a read-only object from what happens in response to that attempt. And that’s what the ManagedObjects/defaultAction mechanism does. Attempts to write are caught and other objects handle what happens in response.
Thinking of this issue in the co text of exception handlers doesn’t make sense. Writes happen all over the system, and not necessarily within the dynamic extent of some computation. The exception handler is global. So one won’t be able to establish exception handlers for all cases. Instead, the global exception system dispatches a per-object-specific response through ManagedObjects.
Marcel Taeumel marcel.taeumel@hpi.de schrieb am Fr., 24. Apr. 2020, 12:10:
But this means the DB is now occupying the use of the readOnly bit,
not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
Best, Marcel
Am 24.04.2020 05:26:56 schrieb Chris Muller ma.chris.m@gmail.com:
So if the exception is unhandled, then before it raises an
UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different
clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something?
Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
On 2020-04-24, at 11:37 AM, Ron Teitelbaum ron@usmedrec.com wrote:
Hi all,
I'd like to add some color here.
Preach it, brother!
See also the fun caused by a do: loop where the block results in an item being removed from the OrderedCollection you're iterating over.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim "Bother" said Pooh as "Formating Drive C" appeared on the screen...
Thanks Ron, I think that I suddenly understand the issue :-)
Dave
On Fri, Apr 24, 2020 at 02:37:52PM -0400, Ron Teitelbaum wrote:
Hi all,
I'd like to add some color here. I worked with Versant for many many years. This problem bites you so hard you need a tourniquet just to survive it.
Imagine looking at your code and trying to understand why something that looks so simple is completely wrong! You spend a huge amount of time trying to understand why the code doesn't actually do what it SAYS it will do. How is this possible? You read and read, you start writing things down but no it is impossible. You feel like you must be missing something extremely simple or are just losing your mind. Then you decide ok I'll take this step by step and validate every message to see exactly where it breaks. You have been looking at this error for over 72 hours straight because someone is standing over your shoulder waiting to ship the product they promised would be available a week ago.
So you get to a method Integer fortyTwo. And it returns #(0) instead of #(42). What the hell is that!!!! The code says ^#(42)!!!!. You can see it right there!!! Then it hits you. I've been bit by a literal variable change! You add copy and now everything works just like you expected it to. Now you need to get the trounequat because after you kicked the trash can you split your knee on the table. Then you go to talk to your colleague and he falls asleep while you are talking to him and his head hits the keyboard. You ask your boss who looks nearly as bad as the comatose colleague what you should do and he says "Save the code!" So you save the code and roll your colleague under the table so nobody steps on him.
This doesn't happen you think?? Well on Versant you couldn't even change the method if the database was holding onto the litteral! Trying to accept a method gave you a database error!!! Oh great fun that was!
Some people have learned the hard way with litteral blood that copy is essential, and for those that haven't you can save them a lot of pain. Changing litterals without the copy is always wrong especially if it will eventually be stored in a database. Imagine doing direct manipulation on a litteral. Now try to explain what happened since the code never actually changed anything!!! How the hell did that happen!!
Try it yourself and then imagine my barely open eyes trying in vain to understand what happened!
Integer class >> fortyTwo ^#(42)
Integer fortyTwo #(42) Integer fortyTwo at: 1 put: 0. Integer fortyTwo #(0)
Go back and look at the method. Hasn't changed still says ^#(42). Good luck debugging that!
I hope that adds some color around this issue. Ok back to your regularly scheduled program!
All the best,
Ron Teitelbaum
On Fri, Apr 24, 2020 at 1:16 PM Eliot Miranda eliot.miranda@gmail.com wrote:
On Apr 24, 2020, at 9:59 AM, Jakob Reschke forums.jakob@resfarm.de wrote:
??? Domain and "data storage" layers are intermixed here, hence the trouble with the concept of read-only. If you don't want such a distinction of layers by using different objects in the first place, then I suggest to at least use separate protocols. So yes, use different managers for different kinds of read-onliness. Your domain-specific layer can still delegate to the VM write barrier if that works well. And different applications can still access the same kind/layer of read-onliness, so Eliot's proposal to have one registry for the VM write barrier handling remains valid.
I'd say each domain should also have an own exception class in this case. As an implementation detail, it could inherit from the base ModificationForbidden... or hide the concrete class behind an accessor.
No. That is unnecessary. The issue is to separate intercepting an attempt to write to a read-only object from what happens in response to that attempt. And that???s what the ManagedObjects/defaultAction mechanism does. Attempts to write are caught and other objects handle what happens in response.
Thinking of this issue in the co text of exception handlers doesn???t make sense. Writes happen all over the system, and not necessarily within the dynamic extent of some computation. The exception handler is global. So one won???t be able to establish exception handlers for all cases. Instead, the global exception system dispatches a per-object-specific response through ManagedObjects.
Marcel Taeumel marcel.taeumel@hpi.de schrieb am Fr., 24. Apr. 2020, 12:10:
But this means the DB is now occupying the use of the readOnly bit,
not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
Best, Marcel
Am 24.04.2020 05:26:56 schrieb Chris Muller ma.chris.m@gmail.com:
So if the exception is unhandled, then before it raises an
UnhandledError it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different
clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something?
Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
Hi Marcel,
My example refers to different use-cases operating on the *same* (identical) set of objects, setting and unsetting the read-only bit willy nilly to suit their purposes, and conflicting with each other. There's only one bit per object.
As far as partitioning within ManagedObjects, I assure it's something you're *definitely* going to need, but you'll still need to ensure all users of beWritableObject, et al, in any one image, are coordinated.
- Chris
On Fri, Apr 24, 2020 at 5:10 AM Marcel Taeumel marcel.taeumel@hpi.de wrote:
But this means the DB is now occupying the use of the readOnly bit,
not available for other applications or use-cases.
Hmmm... ManagedObjects could be partitioned among multiple applications. For example, a game loading some save state could come across some read-only objects and then choses how to manage those. Another application could do this as well, not interfering with the first one. Both might be considered "small DB managers" so to say.
Of course, that check "myDomainObject isReadOnlyObject" would become standard procedure for such DBs, wouldn't it?
Best, Marcel
Am 24.04.2020 05:26:56 schrieb Chris Muller ma.chris.m@gmail.com:
So if the exception is unhandled, then before it raises an UnhandledError
it checks an identity dictionary, which maps object to message, and if the read-only object that was the cause of the error is in the dictionary, instead the exception performs the message with the object as an argument. So a database layer can add the objects it is managing to the map in ModificationForbidden, and mark them as read-only. Then any and all attempts at modifying these objects will cause the database man ager to be notified.
So very simply we can have a pluggable solution that allows different
clients to map the exception into different responses as desired.
But an object in your db table could easily be an Array literal held by a CompiledMethod, not expected to change, but persistent by reference nonetheless. So if the application did then modify it accidentally, instead of Forbidden protection, your DB manager would happily modify it. It's this separation of use-cases is all what the question was about I think, not a big deal, we've lived with unprotected CM literals for this long already, and I've never needed WriteBarrier for anything other than a DB.
Since objects get added to the collection intentionally the array literal would not be added and hence the manager would not modify it.
How would the manager know not to add it? It can't be by checking #isReadOnlyObject, since that presents the same paradox -- requiring the manager to know the business of whatever other use-case has it set. If it assumed it was for CM-literal protection, it wouldn't add it, but what if it was just some debugging or something?
Your example is a straw man.
However, I still don't see the path for how to use this in a complex multi-db Magma application with oblivious objects (e.g., Morphs). It's not something any of the GemStone clients I consulted at as developer or DBA ever had to contend with either, but perhaps not something you're targeting. Squeak is a different animal... I will stay tuned here and watch for the answers as they unfold...
The objects that get added to the wrote barrier management collection get added by managers that want to manage specific objects, not arbitrary objects. Can you see that a DB manager would add objects it has materialized from the DB that it wanted to transparently write-back in modification, and no others?
Yes, absolutely. The manager will get every ModificationForbidden signal under its code whether its meant for the DB or not. Existence in a global table means handle it, otherwise pass it up the stack. But this means the DB is now occupying the use of the readOnly bit, not available for other applications or use-cases.
I hope this critique isn't taken to mean I don't think this isn't a good feature for the VM and image. I do. Everything is a balance of features and limitations. I'm still trying to determine whether Magma can benefit from this, and I have to get deeply critical to find the right decision. I will be following this feature closely, thanks for your patience with my questions.
- Chris
Hi Chris,
On Apr 9, 2020, at 3:16 PM, Chris Muller asqueaker@gmail.com 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 Christoph.Thiede@student.hpi.uni-potsdam.de 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Eliot Miranda eliot.miranda@gmail.com 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 Christoph.Thiede@student.hpi.uni-potsdam.de 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-td510... 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
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 eliot.miranda@gmail.com wrote:
Hi Chris,
On Apr 9, 2020, at 3:16 PM, Chris Muller asqueaker@gmail.com 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 < Christoph.Thiede@student.hpi.uni-potsdam.de> wrote:
Thanks for the fast feedback, I am going to commit this to the Inbox! http://www.hpi.de/
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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Eliot Miranda eliot.miranda@gmail.com *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 < Christoph.Thiede@student.hpi.uni-potsdam.de> 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-td510...
http://forum.world.st/The-Trunk-Kernel-eem-1317-mcz-tp5113273p5113433.html
Best, Christoph
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 ma.chris.m@gmail.com:
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 eliot.miranda@gmail.com wrote:
Hi Chris,
On Apr 9, 2020, at 3:16 PM, Chris Muller asqueaker@gmail.com 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 Christoph.Thiede@student.hpi.uni-potsdam.de 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 squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Eliot Miranda eliot.miranda@gmail.com 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 Christoph.Thiede@student.hpi.uni-potsdam.de 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-td510... 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
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
squeak-dev@lists.squeakfoundation.org