--- a/Exception.st Wed Jan 15 19:08:31 1997 +0100
+++ b/Exception.st Wed Jan 15 21:11:02 1997 +0100
@@ -112,6 +112,48 @@
[author:]
Claus Gittinger
"
+!
+
+examples
+"
+ Examples on Exception-raising & handling are found in the doc/coding
+ section (CodingExamples).
+
+ The emergencyHandler stuff is very useful, to prevent endUser applications
+ from entering the debugger.
+ Some commonly used (useful) emergency handlers are provided in the
+ 'useful handlers' section; try them to learn more
+ (especially, the mailingHandler is fun).
+
+ Define a handler:
+ [exBegin]
+ Exception emergencyHandler:(Exception abortingEmergencyHandler)
+ [exEnd]
+
+
+ try some exception (for demonstration, in some other process):
+ [exBegin]
+ [
+ #(1 2 3) at:4
+ ] fork.
+ [exEnd]
+
+ cleanup:
+ [exBegin]
+ Exception emergencyHandler:nil
+ [exEnd]
+
+
+ A handler which dumps information to a file (watch the file 'errorTrace.stx'):
+ [exBegin]
+ Exception emergencyHandler:(Exception dumpingEmergencyHandler)
+ [exEnd]
+
+ A handler which sends you mail:
+ [exBegin]
+ Exception emergencyHandler:(Exception mailingEmergencyHandler)
+ [exEnd]
+"
! !
!Exception class methodsFor:'initialization'!
@@ -163,28 +205,37 @@
!Exception class methodsFor:'defaults'!
emergencyHandler
- "return the handler used for unhandled exceptions"
+ "return the handler used for unhandled exceptions.
+
+ If no EmergencyHandler has been set, a handler which enters the
+ debugger is returned.
+ The debugger is opened by asking the signal for a debug action,
+ this allows to provide other debuggers in specialized (subclass-instances)
+ of Signal (if that is ever needed)"
"
set it up, when called the first time
"
EmergencyHandler isNil ifTrue:[
- EmergencyHandler := [:ex |
- "
- sending it to the signal allows per-signal specific
- debuggers to be implemented in the future
- (for example, segv in primitive code could show things
- on the C-level ..)
- "
- (ex signal) enterDebuggerWith:ex message:(ex errorString).
- ]
+ EmergencyHandler := [:ex |
+ "
+ sending it to the signal allows per-signal specific
+ debuggers to be implemented in the future
+ (for example, segv in primitive code could show things
+ on the C-level ..)
+ "
+ (ex signal) enterDebuggerWith:ex message:(ex errorString).
+ ]
].
^ EmergencyHandler
+
+ "Modified: 15.1.1997 / 20:50:37 / cg"
!
emergencyHandler:aOneArgBlock
- "set the handler used for unhandled exceptions"
+ "set the handler used for unhandled exceptions.
+ The default (a nil-handler) leads to a debugger to be shown."
EmergencyHandler := aOneArgBlock
@@ -218,7 +269,214 @@
[:ex | Smalltalk exitWithCoreDump. ]
"
- "Modified: 7.1.1997 / 21:15:07 / cg"
+ "Modified: 15.1.1997 / 20:49:06 / cg"
+! !
+
+!Exception class methodsFor:'useful handlers'!
+
+abortingEmergencyHandler
+ "return a block (usable as an emergency handler),
+ which aborts after showing a warnBox.
+ This is useful for endUser applications"
+
+ ^ [:ex | self warn:'Error: ' , ex errorString.
+ AbortSignal raise
+ ]
+
+ "test with (try a few halts or CTRL-C's):
+ Exception emergencyHandler:(Exception abortingEmergencyHandler)
+ "
+
+ "back with:
+ Exception emergencyHandler:(Exception notifyingEmergencyHandler)
+ Exception emergencyHandler:nil
+ "
+
+ "Created: 15.1.1997 / 20:13:06 / cg"
+ "Modified: 15.1.1997 / 20:15:02 / cg"
+!
+
+dumpingEmergencyHandler
+ "return a block (usable as an emergency handler),
+ which dumps the stackBacktrace to a trace file and
+ aborts after showing a warnBox.
+ This is useful, for endUser application, which are still being
+ debugged (i.e. the programmers may have a look at the traceFile
+ from time to time).
+
+ Notice:
+ The code below is just an example; you may want to change the
+ name of the error-file in your application
+ (but please: copy the code; do not modify here)"
+
+ ^ [:ex |
+ |str printedException|
+
+ ex signal == Signal noHandlerSignal ifTrue:[
+ printedException := ex parameter.
+ ] ifFalse:[
+ printedException := ex
+ ].
+
+ "/ user interruption is handled specially:
+ "/ allow user to choose between proceeding or aborting
+ "/ but never dump that information to the file.
+
+ printedException signal == Object userInterruptSignal ifTrue:[
+ (self confirm:'abort current action ?') ifTrue:[
+ AbortSignal raise
+ ].
+ ex proceed
+ ].
+
+ "/
+ "/ dump it to 'errorTrace.stx'
+ "/
+ str := 'errorTrace.stx' asFilename appendingWriteStream.
+
+ str nextPutLine:('******************************* '
+ , AbsoluteTime now printString
+ , ' *******************************').
+ str cr.
+
+ str nextPutLine:('** Error: ' , printedException errorString).
+ str nextPutLine:('** Signal: ' , printedException signal printString).
+ str nextPutLine:('** Parameter: ' , printedException parameter printString).
+ str nextPutLine:('** Process: ' , Processor activeProcess printString).
+ str nextPutLine:('** Backtrace:').
+ str cr.
+
+ printedException suspendedContext fullPrintAllOn:str.
+ str cr.
+ str cr.
+ str close.
+
+ self warn:printedException errorString.
+ AbortSignal raise
+ ]
+
+ "test with (try a few halts or CTRL-C's):
+ Exception emergencyHandler:(Exception dumpingEmergencyHandler)
+ "
+
+ "back with:
+ Exception emergencyHandler:(Exception notifyingEmergencyHandler)
+ Exception emergencyHandler:nil
+ "
+
+ "Created: 15.1.1997 / 20:14:52 / cg"
+ "Modified: 15.1.1997 / 21:07:14 / cg"
+!
+
+mailingEmergencyHandler
+ "return a block (usable as an emergency handler),
+ which shows a warnBox and optionally mails a stackBacktrace to a maintainer.
+ This is useful, for endUser application, which are still being
+ debugged (i.e. the programmers may have a look at the errors).
+
+ Notice: the stuff here is a demonstration only; it should be modified
+ for your particular environment ...
+ ... but please: copy the code and modify there;
+ leave the stuff below as it is."
+
+ ^ [:ex |
+ |str printedException doMail emergencyMailReceiver pipe|
+
+ ex signal == Signal noHandlerSignal ifTrue:[
+ printedException := ex parameter.
+ ] ifFalse:[
+ printedException := ex
+ ].
+
+ "/ user interruption is handled specially:
+ "/ allow user to choose between proceeding or aborting
+ "/ but never dump that information to the file.
+
+ printedException signal == Object userInterruptSignal ifTrue:[
+ (self confirm:'abort current action ?') ifTrue:[
+ AbortSignal raise
+ ].
+ ex proceed
+ ].
+
+ "/ somehow get the name of the guy to receive the mail
+ "/ you have to implement that yourself.
+
+ "/ emergencyMailReceiver := OneOfYourClass getEmergencyMailReceiver.
+ emergencyMailReceiver := OperatingSystem getLoginName.
+
+ emergencyMailReceiver isNil ifTrue:[
+ self warn:(printedException errorString
+ , '\\No mailing to service people possible.') withCRs.
+ doMail := false.
+ ] ifFalse:[
+ doMail := self confirm:(printedException errorString
+ , '\\Mail error information to the service people ('
+ , emergencyMailReceiver , ') ?') withCRs
+ ].
+ doMail ifTrue:[
+ str := '' writeStream.
+
+ str nextPutLine:('Error notification from '
+ , OperatingSystem getLoginName
+ , '@'
+ , OperatingSystem getHostName).
+ str cr.
+
+ str nextPutLine:('Time: ' , AbsoluteTime now printString).
+ str nextPutLine:('Error: ', printedException errorString).
+ str nextPutLine:('Signal: ', printedException signal printString).
+ str nextPutLine:('Parameter: ', printedException parameter printString).
+ str nextPutLine:('Process: ', Processor activeProcess printString).
+ str nextPutLine:'Backtrace:'.
+ str cr.
+
+ printedException suspendedContext fullPrintAllOn:str.
+ str cr;cr.
+
+ str close.
+
+ pipe := PipeStream
+ writingTo:'mail ', emergencyMailReceiver.
+ pipe notNil ifTrue:[
+ pipe nextPutLine:'Subject: automatic error report'.
+ pipe nextPutAll:str contents.
+ pipe cr.
+ pipe close.
+ ]
+ ].
+
+ AbortSignal raise
+ ]
+
+ "test with (try a few halts or CTRL-C's):
+ Exception emergencyHandler:(Exception mailingEmergencyHandler)
+ "
+
+ "back with:
+ Exception emergencyHandler:(Exception notifyingEmergencyHandler)
+ Exception emergencyHandler:nil
+ "
+
+ "Created: 15.1.1997 / 20:14:52 / cg"
+ "Modified: 15.1.1997 / 21:10:28 / cg"
+!
+
+notifyingEmergencyHandler
+ "return a block (usable as an emergency handler for exceptions),
+ which does errorNotification before going into the debugger."
+
+ ^ [:ex | nil errorNotify:ex errorString from:ex suspendedContext ]
+
+ "test with (try a few halts or CTRL-C's):
+ Exception emergencyHandler:(Exception notifyingEmergencyHandler)
+ "
+
+ "back with:
+ Exception emergencyHandler:nil
+ "
+
+ "Modified: 15.1.1997 / 20:15:12 / cg"
! !
!Exception methodsFor:'accessing'!
@@ -607,6 +865,6 @@
!Exception class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.43 1997-01-07 20:42:18 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.44 1997-01-15 20:11:02 cg Exp $'
! !
Exception initialize!