[squeak-dev] handling Notification safely
Chris Muller
asqueaker at gmail.com
Tue Oct 11 02:58:41 UTC 2011
It appears that handling Notification can result in an unexpectedly
brittle situation if the code also ever uses
String>>#displayProgressFrom:to:during:.
Background: I'm using use a CommandLineProcessor class to run batch
jobs in headless mode. I use a high-level handler on Notification and
Warning to write any messages to stdout thusly:
| stdOut stdErr |
self ensureStartedUp.
stdOut := StandardFileStream stdout.
stdErr := StandardFileStream stderr.
[ aBlock valueWithAllArguments: self args ]
on: Notification , Warning
do:
[ : noti | stdOut
nextPutAll: DateAndTime now asString ;
space ;
nextPutAll: noti description ;
perform: MultiByteFileStream lineEndDefault.
noti resume ]
However, some of the code run by aBlock valueWithAllArguments: ends up
doing its work under Squeak's standard progress-notifying facility,
String>>#displayProgressFrom:to:during:. The result is that
explicitly handling Notification implicitly handles
ProgressInitiationExceptions, and therefore
ProgressInitiationException>>#defaultAction does not run, which means
that the code being monitored does not run. Silently. Yikes!
Behold with an example:
| receivedSignal resumed |
receivedSignal := resumed := false.
[ "client-code puts up progress, and signals some notications"
| count | count := 0.
'doing something'
displayProgressFrom: 0 to: 10 during:
[ : bar |
10 timesRepeat:
[ bar value: (count:=count+1).
(Delay forMilliseconds: 500) wait.
Notification signal: 'message'.
resumed:=true ] ] ]
on: Notification
do:
[ : noti | receivedSignal:=true.
noti resume ].
self
assert: receivedSignal ;
assert: resumed
So, I suppose we need to handle ProgressInitiationException
separately, and call the #defaultAction.
| receivedSignal resumed |
receivedSignal := resumed := false.
[ "client-code puts up progress, and signals some notications"
| count | count := 0.
'doing something'
displayProgressFrom: 0 to: 10 during:
[ : bar |
10 timesRepeat:
[ bar value: (count:=count+1).
(Delay forMilliseconds: 500) wait.
Notification signal: 'message'.
resumed:=true ] ] ]
+ on: ProgressInitiationException
+ do: [ : prog | prog defaultAction ]
on: Notification, Warning
do:
[ : noti | receivedSignal:=true.
noti resume ].
self
assert: receivedSignal ;
assert: resumed
This strikes me as a remarkably fierce penalty for something this
non-obvious. Should it be improved?
- Chris
More information about the Squeak-dev
mailing list
|