%% An abstract: %% %% Exception safety is a difficult topic in any language. In non-GC'd languages %% like C++, it can be very hard to write exception-safe code. In Ruby, it's a %% little easier, but there are still quite a few "gotchas". %% %% The goal of this talk is to discuss some of the exception safety issues that %% show up on the mailing list, to propose some solutions, and to discuss %% problems not yet solved. If time permits, exception-safety in Ruby extensions %% written in C and C++ will also be discussed. Some knowledge of C/C++ is %% recommended but not required. %% %% An outline: %% %% I. Exception safety in Ruby %% A. Resource allocation/deallocation %% 1. finalizers - hard to use, doesn't guarantee cleanup %% 2. blocks - guaranteed cleanup, but potentially more expensive %% B. Exception safety guarantees %% 1. basic guarantee - invariants preserved, no resources leaked %% 2. strong guarantee - state remains the same if an exception is thrown %% a. ensure block - useful for rolling-back static operations %% b. undo/rollback - rollback dynamic operations in reverse order %% (see RubyTreasures and MetaRuby) %% 3. no-throw guarantee - necessary when operations cannot be undone %% C. Intercepting exceptions (with ensure) %% a. re-raising the exception doesn't always work %% b. using ensure to intercept the exception means the exception can be %% propogated without being re-raised. %% E. Some functions must NOT raise exceptions %% 1. freeze %% a. makes "deep freeze" difficult if it can raise exceptions (since %% "unfreeze" is impossible (note that taint/untaint are okay, since %% they are undoable). %% b. [ruby-talk:40022] %% 2. each %% a. necessary for implementing freeze in some objects %% b. CAN pass exceptions raised in the block (since it is user code) %% 3. <=>, ==, finalizers %% a. Exception will not get propogated nor printed, just ignored %% b. [ruby-talk:40612] %% 4. The * operator %% a. Used for multiple assignment, calls to_a() %% b. If to_ary() fails, then * can fail, so don't use it for swap() %% operations. %% E. Error messages (reference Andrei's talk) %% 1. Good exception message != good error message %% 2. How to write a generic component for generating error messages? %% F. Exceptions in threads %% 1. abort_on_exception - forgetting it is a common mistake %% 2. alternative: catch exception at highest level and log it %% G. Errno exceptions %% 1. Where Ruby 1.6.x returns an error code, %% 2. Ruby 1.7.x raises an Errno::xxx exception. %% %% II. Exception safety in extensions %% A. C - easy; C++ - hard %% B. First try: rb_rescue2 (doesn't work with catch/throw) %% C. Second try: rb_protect (how do I re-throw the symbol?) %% 1. This technique used by Exceptional Ruby (my wrapper for writing %% exception-safe C++ extensions) %% D. Alternative: allocate everything on the heap and register it with the %% Ruby GC %% %% III. Resources %% A. http://rm-f.net/~cout/ruby/treasures/RubyTreasures-0.4/lib/exc/ %% B. http://www.gotw.ca/publications/xc++.htm %% C. http://www.boost.org/more/generic_exception_safety.html %% D. http://www.metabyte.com/~fbp/stl/eh_contract.html %% %% Default fonts %deffont "standard" xfont "helvetica-medium-r", tfont "arial.ttf", tmfont "arial.ttf" %deffont "thick" xfont "helvetica-bold-r", tfont "arialb.ttf", tmfont "arialb.ttf" %deffont "typewriter" xfont "fixed-medium-r", tfont "cour.ttf", tmfont "cour.ttf" %% %% Default settings per each line number %default 1 area 90 90, leftfill, size 2, fore "yellow", back "black", font "thick", bgrad %default 2 size 6, vgap 10, prefix " ", ccolor "black" %default 3 size 2, bar "gray70", vgap 10 %default 4 size 5, fore "white", vgap 30, prefix " ", font "standard" %% %% Default settings for tab-indented lines %tab 1 size 5, vgap 40, prefix " ", icon box "green" 50 %tab 2 size 4, vgap 40, prefix " ", icon arc "yellow" 50 %tab 3 size 3, vgap 40, prefix " ", icon delta3 "white" 40 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page %center Exceptional Ruby Ruby Conference 2002 Paul Brannan paul@atdesk.com %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Overview Exceptions happen We need to deal with them correctly A program shouldn't crash just because it gets an exception A program should never have undefined behavior A program should never leak resources GC makes the job easier, but doesn't solve it. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page A Simple Example %% #ruby <