It's clearly a bug in Installer. I guess this fixes it:
noProgressDuring: block
[ block value: self ] on: ProgressInitiationException do: [ :note | note sendNotificationsTo: [ :min :max :curr | "ignore" ] ]
Oh wow sendNotificationsTo: since 2000 (blush). Ok.
I want to catch Notifications and Warnings at the highest level, log them and resume. If there was a lower-handler then my high-level
Why?
Well, because the class comment for Notification says:
"A Notification is an indication that something interesting has occurred. If it is not handled, it will pass by without effect."
and when I run a headless image, I want to know about everything "interesting" that occurs - so I was simply printing its messageText to a log and resuming.
The phrase "If it is not handled" implies that it _can_ be handled. The phrase, "pass by without effect" implies a notification that isn't handled is no more useful than a simple method.
Warnings are okay, because those only inform the user about some issue that can be ignored at own risk, but Notifications are used for all kind of stuff that involves passing objects up and/or down the stack. Catching them without proper handling can and will break stuff.
noti resume should _always_ be a proper way to handle any kind of Notification. That's the particular contract I believe being a subclass of Notification should guarantee. ProgressInitiationException has broken that contract.
I have the feeling that you think about a Notification as an exception that passes some information about the system and swallowing it is harmless, like Warning or an info or notice level message in syslog. Notifications are Exceptions with a well-defined #defaultAction. So it's always safe to throw and not catch them.
Not ever catching a notification (of any particular type) would mean it serves no purpose that couldn't have been done with a simple method (for its defaultAction behavior).
Likewise, if Notification itself cannot/should-not be ever caught anywhere, then it serves no real purpose other than to be a "organizer" superclass (since no one would use it for it's defaultAction). Now that may be the case, but then what type of exceptions is it organizing? By the name Notification, it would seem to be the "type" that are meant to be resumed.
So if, by swallow, you mean handle _and_ resume the Notification, then yes, that's how I think about them.
I totally get some Notification sub-types require special handling - I have one I use all the time called MagmaSessionRequest so that domain-level code can signal transaction-control to the higher-level code which has access to the session.
BUT it doesn't break the "contract" that I can catch it as long as I resume it:
[ Transcript cr; show: 'pre-commit code'. MagmaSessionRequest signalCommit. "<--- requires special-handling to be useful" Transcript cr; show: 'post-commit code' ] on: Notification do: [ : noti | Transcript cr; show: noti messageText. noti resume ].
prints
pre-commit code committing transaction post-commit code
I don't think of Notifications are intended to be used in cases involving truncating execution and unwinding the stack. For that, some other subclass of Exception should be employed.
That's why Notification's defaultAction surprises me very much -- it appears as useless.
Someone else thought the same way I do and that's why ProgressInitiationException resulted in Installer being badly broken for over three years unnoticed -- partially because the code *looks* fine. The only way to know for sure is to look into each and every Notification see how it works.
Which leads me right back to my question: If I have to look at each kind of Notification to see how it works, then someone please tell me what type of exception is this "organizing superclass" organizing? There should be some commonality to all of its subclasses, what is it?
- Chris
I completely agree with you. A Notification(s) should always resume normal execution, for other kinds of exception which may change the program flow there are different categories.
We should assume, that
Notification signal.
should have no any effects if there is no handler(s) of it in caller's contexts as well as we should assume that handlers should never attempt to change the program flow.
Concerning progress bar and use of notifications in it: every time i look at this code i get confused.
There must be a better ways to implement that without a need to use exceptions. I think this stuff is a bit overengineered. I don't understand why we just can't have something as simple as:
ProgressBar showProgressFrom: x to: y during: [:bar |
x to: y do: [:i | "whatever i do in a loop ... " bar advance ]
]. what could be simpler?
On 20 October 2011 04:50, Chris Muller asqueaker@gmail.com wrote:
It's clearly a bug in Installer. I guess this fixes it:
noProgressDuring: block
[ block value: self ] on: ProgressInitiationException do: [ :note | note sendNotificationsTo: [ :min :max :curr | "ignore" ] ]
Oh wow sendNotificationsTo: since 2000 (blush). Ok.
I want to catch Notifications and Warnings at the highest level, log them and resume. If there was a lower-handler then my high-level
Why?
Well, because the class comment for Notification says:
"A Notification is an indication that something interesting has occurred. If it is not handled, it will pass by without effect."
and when I run a headless image, I want to know about everything "interesting" that occurs - so I was simply printing its messageText to a log and resuming.
The phrase "If it is not handled" implies that it _can_ be handled. The phrase, "pass by without effect" implies a notification that isn't handled is no more useful than a simple method.
Warnings are okay, because those only inform the user about some issue that can be ignored at own risk, but Notifications are used for all kind of stuff that involves passing objects up and/or down the stack. Catching them without proper handling can and will break stuff.
noti resume should _always_ be a proper way to handle any kind of Notification. That's the particular contract I believe being a subclass of Notification should guarantee. ProgressInitiationException has broken that contract.
I have the feeling that you think about a Notification as an exception that passes some information about the system and swallowing it is harmless, like Warning or an info or notice level message in syslog. Notifications are Exceptions with a well-defined #defaultAction. So it's always safe to throw and not catch them.
Not ever catching a notification (of any particular type) would mean it serves no purpose that couldn't have been done with a simple method (for its defaultAction behavior).
Likewise, if Notification itself cannot/should-not be ever caught anywhere, then it serves no real purpose other than to be a "organizer" superclass (since no one would use it for it's defaultAction). Now that may be the case, but then what type of exceptions is it organizing? By the name Notification, it would seem to be the "type" that are meant to be resumed.
So if, by swallow, you mean handle _and_ resume the Notification, then yes, that's how I think about them.
I totally get some Notification sub-types require special handling - I have one I use all the time called MagmaSessionRequest so that domain-level code can signal transaction-control to the higher-level code which has access to the session.
BUT it doesn't break the "contract" that I can catch it as long as I resume it:
[ Transcript cr; show: 'pre-commit code'. MagmaSessionRequest signalCommit. "<--- requires special-handling to be useful" Transcript cr; show: 'post-commit code' ] on: Notification do: [ : noti | Transcript cr; show: noti messageText. noti resume ].
prints
pre-commit code committing transaction post-commit code
I don't think of Notifications are intended to be used in cases involving truncating execution and unwinding the stack. For that, some other subclass of Exception should be employed.
That's why Notification's defaultAction surprises me very much -- it appears as useless.
Someone else thought the same way I do and that's why ProgressInitiationException resulted in Installer being badly broken for over three years unnoticed -- partially because the code *looks* fine. The only way to know for sure is to look into each and every Notification see how it works.
Which leads me right back to my question: If I have to look at each kind of Notification to see how it works, then someone please tell me what type of exception is this "organizing superclass" organizing? There should be some commonality to all of its subclasses, what is it?
- Chris
On Wed, 19 Oct 2011, Chris Muller wrote:
It's clearly a bug in Installer. I guess this fixes it:
noProgressDuring: block
[ block value: self ] on: ProgressInitiationException do: [ :note | note sendNotificationsTo: [ :min :max :curr | "ignore" ] ]
Oh wow sendNotificationsTo: since 2000 (blush). Ok.
I want to catch Notifications and Warnings at the highest level, log them and resume. If there was a lower-handler then my high-level
Why?
Well, because the class comment for Notification says:
"A Notification is an indication that something interesting has occurred. If it is not handled, it will pass by without effect."
Um, yeah, but it's being used for quite different things nowadays.
and when I run a headless image, I want to know about everything "interesting" that occurs - so I was simply printing its messageText to a log and resuming.
Sounds right, but some Notifications do not conform to that method comment.
The phrase "If it is not handled" implies that it _can_ be handled.
But some Notifications require special handling.
The phrase, "pass by without effect" implies a notification that isn't handled is no more useful than a simple method.
Warnings are okay, because those only inform the user about some issue that can be ignored at own risk, but Notifications are used for all kind of stuff that involves passing objects up and/or down the stack. Catching them without proper handling can and will break stuff.
noti resume should _always_ be a proper way to handle any kind of Notification. That's the particular contract I believe being a subclass of Notification should guarantee. ProgressInitiationException has broken that contract.
Right, as long as we stick to that class comment.
I have the feeling that you think about a Notification as an exception that passes some information about the system and swallowing it is harmless, like Warning or an info or notice level message in syslog. Notifications are Exceptions with a well-defined #defaultAction. So it's always safe to throw and not catch them.
Not ever catching a notification (of any particular type) would mean it serves no purpose that couldn't have been done with a simple method (for its defaultAction behavior).
It's safe to catch, it's not safe to swallow.
Likewise, if Notification itself cannot/should-not be ever caught anywhere, then it serves no real purpose other than to be a "organizer" superclass (since no one would use it for it's defaultAction). Now that may be the case, but then what type of exceptions is it organizing? By the name Notification, it would seem to be the "type" that are meant to be resumed.
So if, by swallow, you mean handle _and_ resume the Notification, then yes, that's how I think about them.
I totally get some Notification sub-types require special handling - I have one I use all the time called MagmaSessionRequest so that domain-level code can signal transaction-control to the higher-level code which has access to the session.
BUT it doesn't break the "contract" that I can catch it as long as I resume it:
[ Transcript cr; show: 'pre-commit code'. MagmaSessionRequest signalCommit. "<--- requires special-handling to be useful" Transcript cr; show: 'post-commit code' ] on: Notification do: [ : noti | Transcript cr; show: noti messageText. noti resume ].
prints
pre-commit code committing transaction post-commit code
I don't think of Notifications are intended to be used in cases involving truncating execution and unwinding the stack. For that, some other subclass of Exception should be employed.
The problem is that Notifications are widely used for passing objects up and down the stack. If you #resume these Notifications, you'll stop these "communication channels" and break the system. For example in the core image the following Notifications can't be swallowed (just resumed) without side effects:
AmbiguousSelector ExceptionAboutToReturn InMidstOfFileinNotification MCChangeSelectionRequest MCVersionNameAndMessageRequest OutOfScopeNotification ParserNotification PickAFileToWriteNotification ProjectEntryNotification ProjectPasswordNotification ProjectViewOpenNotification ReparseAfterSourceEditing TimedOut UndeclaredVariable UndefinedVariable UnknownSelector UnusedVariable
That's why Notification's defaultAction surprises me very much -- it appears as useless.
It just ensures that it's safe to signal the notification.
Someone else thought the same way I do and that's why ProgressInitiationException resulted in Installer being badly broken for over three years unnoticed -- partially because the code *looks* fine. The only way to know for sure is to look into each and every Notification see how it works.
Which leads me right back to my question: If I have to look at each kind of Notification to see how it works, then someone please tell me what type of exception is this "organizing superclass" organizing? There should be some commonality to all of its subclasses, what is it?
Maybe it's worth separating the Notifications which just provide some information and can simply be resumed from those which are used for communication across the stack.
Levente
- Chris
Am 2011-10-21 um 01:22 schrieb Levente Uzonyi:
Which leads me right back to my question: If I have to look at each kind of Notification to see how it works, then someone please tell me what type of exception is this "organizing superclass" organizing? There should be some commonality to all of its subclasses, what is it?
Maybe it's worth separating the Notifications which just provide some information and can simply be resumed from those which are used for communication across the stack.
Among these ‘communication notifications’ is the Seaside WADynamicVariable, wich leads me to the impression, that—since there are now Thread-local based dynamic variables in trunk—communication notifications can be re-modeled to be actual dynamic variables (which some of them seem to be)
Best -Tobias
On 21 October 2011 07:52, Tobias Pape Das.Linux@gmx.de wrote:
Am 2011-10-21 um 01:22 schrieb Levente Uzonyi:
Which leads me right back to my question: If I have to look at each kind of Notification to see how it works, then someone please tell me what type of exception is this "organizing superclass" organizing? There should be some commonality to all of its subclasses, what is it?
Maybe it's worth separating the Notifications which just provide some information and can simply be resumed from those which are used for communication across the stack.
Among these ‘communication notifications’ is the Seaside WADynamicVariable, wich leads me to the impression, that—since there are now Thread-local based dynamic variables in trunk—communication notifications can be re-modeled to be actual dynamic variables (which some of them seem to be)
I started looking into the interplay between DynamicVariable and my work on partial continuations. From a theoretical standpoint they should interact badly [1] but maybe the implementation of DynamicVariable actually corresponds to Kiselyov's "DB+DC". As I say, I haven't devoted the time to find out, even though it's an issue close to my heart.
[1] http://okmij.org/ftp/Computation/dynamic-binding.html
frank
On Fri, 21 Oct 2011, Tobias Pape wrote:
Am 2011-10-21 um 01:22 schrieb Levente Uzonyi:
Which leads me right back to my question: If I have to look at each kind of Notification to see how it works, then someone please tell me what type of exception is this "organizing superclass" organizing? There should be some commonality to all of its subclasses, what is it?
Maybe it's worth separating the Notifications which just provide some information and can simply be resumed from those which are used for communication across the stack.
Among these ?communication notifications? is the Seaside WADynamicVariable, wich leads me to the impression, that?since there are now Thread-local based dynamic variables in trunk?communication notifications can be re-modeled to be actual dynamic variables (which some of them seem to be)
Yes, some of them can easily be changed to use DynamicVariable (if the communication direction is bottom to top and no lazy initialization is involved), but others are a bit tedious to implement this way. I think the best solution would be to separate these communication exceptions from Notification by creating a new subclass of Exception for them.
Levente
Best -Tobias
squeak-dev@lists.squeakfoundation.org