SYS-EXCEPTION(2) SYS-EXCEPTION(2) NAME Exception, raise, rescue, rescued, unrescue - exception handling SYNOPSIS include "sys.m"; sys := load Sys Sys->PATH; Exception: adt { name: string; # name of exception mod: string; # module pc: int; # program counter }; raise: fn(s: string); rescue: fn(s: string, e: ref Exception): int; rescued: fn(flag: int, s: string); unrescue: fn(); DESCRIPTION These functions provide exception handling in Limbo. Exception communicates the nature of the exception. Exception.pc is the virtual machine program counter at the point of the raised exception, relative to the start of the module. Raise throws an exception with the name s, and sets the error string for sys-print(2) (the value of the format %r) to s. Rescue installs a rescue block for exceptions matched by s. If a matching exception occurs, rescue will return Sys->EXCEPTION; otherwise it returns Sys->HANDLER. S matches an exception name when the two are equal, or s is a string (the prefix) followed by *, which matches any excep- tion name starting with the same prefix. In particular, "*" matches all exceptions. Rescue blocks can only handle exceptions that are raised in the same thread. If an excep- tion needs to be handled in a spawned thread, a rescue block must be installed there. if(sys->rescue("fail:*", e) == Sys->EXCEPTION) { # exception handling code ... sys->rescued(Sys->EXIT, nil); } Rescued tells the system what to do after an exception has been handled, as specified by flag: Page 1 Plan 9 (printed 11/17/24) SYS-EXCEPTION(2) SYS-EXCEPTION(2) ACTIVE Leave the handler installed; execution continues. RAISE Re-raise this exception or raise a different one. If s is nil, the current exception is re-raised; otherwise, exception s is raised instead. EXIT The thread exits. ONCE Remove the handler; execution continues. For exam- ple: if(sys->rescue("an exception", e) == Sys->HANDLER) { # normal execution code here } else { # handler code here sys->rescued(Sys->ONCE, nil); # removes the handler } Unrescue removes the most recently installed handler and continues execution. EXAMPLES The first example removes the handler if normal execution completes: if(sys->rescue("an exception", e) == Sys->HANDLER) { # normal execution code here sys->unrescue(); } else { # exception handling code here } The next example is a complete program that demonstrates the behaviour of exception handling by executing both the normal execution code and the handler code. implement Excep; include "sys.m"; sys: Sys; include "draw.m"; Excep: module { init: fn(ctxt: ref Draw->Context, argv: list of string); }; init(ctxt: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; e := ref sys->Exception; if(sys->rescue("an exception", e) == Sys->EXCEPTION) { sys->print("rescue: exception\n"); sys->print("e.name = %s\ne.mod = %s\ne.pc = %d\n", e.name, e.mod, e.pc); Page 2 Plan 9 (printed 11/17/24) SYS-EXCEPTION(2) SYS-EXCEPTION(2) sys->rescued(Sys->ONCE, nil); } else { sys->print("rescue: normal execution\n"); sys->raise("an exception"); } sys->print("raise: %r\n"); sys->raise("nasty thing"); # won't be handled } SEE ALSO sh(1), prog(3) Page 3 Plan 9 (printed 11/17/24)