Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add missing calls to xbt_ex_free().
[simgrid.git] / doc / gtut-tour-08-exceptions.doc
1 /**
2 @page GRAS_tut_tour_exceptions Lesson 8: Handling errors through exceptions
3
4 \section GRAS_tut_tour_exceptions_toc Table of Contents
5  - \ref GRAS_tut_tour_exceptions_intro
6  - \ref GRAS_tut_tour_exceptions_use
7  - \ref GRAS_tut_tour_exceptions_recap
8    
9 <hr>
10
11 \section GRAS_tut_tour_exceptions_intro Introduction
12
13 Exceptions are a great mecanism to deal with error exception, everyone knows
14 that.
15
16 Without exceptions, you have to rely on returning a value indicating whether
17 the function call were right or not, and check the return values of every
18 single function you call. If there is one point in the calling sequence
19 where your forgot this check, the chain is broken and caller won't notice
20 the issue. In practice, dealing with error without exceptions loads user
21 code with *tons* of those stupid checks and you loose your functional code
22 in the middle of that miasm.
23
24 With them, you simply write your code. If you want to deal with errors (ie,
25 you actually know how to react to errors at this point of your code), you
26 write a catching block. If you don't, you don't. And exceptions flow through
27 from trowing point to catching point without bothering you.
28
29 At this point, you may be a bit surprised by the previous paragraphs.
30 SimGrid and GRAS are written in C, and everybody knows that there is no
31 exception in C but only in C++, Java and such. This is true, exceptions are
32 not part of the C language, but this is such a great tool that we
33 implemented an exception mecanism as part of the SimGrid library (with
34 setjmp and longjmp, for the curious). 
35
36 Being "home-grown" make our exception mecanic both stronger and weaker at
37 the same time. First it is weaker because, well, we are more limitated
38 within the library as we are than if we could change the compiler itself to
39 add some extra checks here and specific treatment there. But it is also a
40 advantage for us, since the exception mecanism is perfectly fitted to the
41 distributed settings of GRAS processes. They can easily propagate on the
42 net, as we will see in the next lesson (\ref GRAS_tut_tour_rpc) and contain
43 information about the host on which they were thrown (#xbt_ex_t) along with
44 the thrown point in the source code.
45
46 The syntax of XBT exceptions should not sound unfamilliar to most of you.
47 You throw them using the #THROW and #THROWF macros. They take 2 arguments:
48 an error category (of type #xbt_errcat_t) and an error "value" (an integer;
49 pratically, this is often left to 0 in my own code). #THROWF also takes a
50 message string as extra argument which is a printf-like format string with
51 its own arguments. So, you may have something like the following:
52 \verbatim THROWF(system_error, 0, "Cannot connect to %s:%d because of %s", hostname, port, reason);\endverbatim
53
54 Then, you simply add a #TRY/#CATCH block around your code:
55 \verbatim TRY{ 
56   /* your code */ 
57 } CATCH(e) { 
58   /* error handling code */
59 } \endverbatim
60
61 Another strange thing is that you should actually free the memory allocated
62 to the exception with xbt_ex_fres() if you manage to deal with them. There
63 is a bit more than this on the picture (#TRY_CLEANUP blocks, for example), and
64 you should check the section \ref XBT_ex for more details.
65
66 You should be <b>very carfull</b> when using the exceptions. They work great
67 when used correctly, but there is a few golden rules you should never break.
68 Moreover, the error messages and symptom can get <b>really crude</b> when
69 misusing the exceptions.
70
71  - <b>Do not move out of a TRY block with a return, a break or any other
72    kind of jump. NEVER. EVER.</b>. This is the most tempting error, and this
73    drives the system nuts. You will probably segfault in the next exception
74    raising, far away from where you incidentally typed <tt>return</tt>
75    (this is because there is some cleanups to do at the end of a TRY block,
76    you cannot just leave it).
77  - <b>Play safe with variables modified in the TRY block</b>. You may want
78    to mark them as <tt>volatile</tt>, which is a modifier (just like
79    <tt>const</tt>) indicating that the value of the denoted variable may get
80    changed by external parts of the program during the run. This is the case
81    when your data gets modified by an exception raising function, I guess.
82
83 So, as you can see, you don't want to include large sections of your program
84 in TRY blocks. If you do so, it's quite sure that one day, you'll do a break
85 or a return within this block. And believe me, finding such typos is a real
86 pain. 
87
88 If you are suspecting this kind of error, I made a little script for you:
89 check <tt>tools/xbt_exception_checker</tt> from the CVS. Given a set of C
90 files, it extracts the TRY blocks and display them on the standard output so
91 that you can grep for <tt>return</tt>, <tt>break</tt> and such forbidden
92 words.
93
94 \section GRAS_tut_tour_exceptions_use Putting exceptions into action
95
96 Okay. I hope those little warnings didn't discourage you from using the
97 exceptions, because they really are a nice mecanism. We will now change a
98 bit our program to take advantage of them. The only issue is that when a
99 program run properly, it usually don't raise any exception. We could protect
100 the calls we already have with exception handling, but it wouldn't be really
101 exciting since we know this code does not throw any exception under the
102 condition we use (actually, most of the GRAS functions may throw exception
103 on problem).
104
105 Instead, we will code a little game between the client and the server. We
106 won't tell the client the exact port on which the server listen, and it will
107 have to find from itself. For this, it will try to open socket and send the
108 kill message to each ports of the search range. If it manage to close the
109 socket after sending the message without being interrupted by an exception,
110 it can assume that it killed the server and stop searching.
111 \dontinclude 08-exceptions.c
112 \skip port=3000
113 \until end_of_loop
114
115 To make the game a bit more fun (and to show you what an exception actually
116 look like when it's not catched), we add a potential command line argument
117 to the server, asking it to cheat and to not open its port within the search
118 range but elsewhere:
119 \dontinclude 08-exceptions.c
120 \skip strcmp
121 \until gras_socket_my_port
122 \until }
123
124 Then, when the client detects that it didn't manage to find&destroy the
125 server, it throws a suicide exception (sorry for the bad jokes):
126 \skip if(!found)
127 \until THROW
128
129 \section GRAS_tut_tour_exceptions_recap Recapping everything together
130
131 Here is the output produced by this new program. Note that when the program
132 bails out because of an uncatched exception, it displays its backtrace just
133 like a JVM would do (ok, it'a a bit cruder than the one of the JVM, but
134 anyway). For each function frame of the calling stack, it displays the
135 function name and its location in the source files (if it manage to retrieve
136 it). Don't be jalous, you can display such stacks wherever you want with 
137 xbt_backtrace_display() ;)
138
139 Unfortunately, this feature is only offered under Linux for now since I have
140 no idea of how to retrieve the call stack of the current process under the
141 other operating systems. But help is always welcome in this area too ;)
142
143 \include 08-exceptions.output
144
145 The complete program reads:
146 \include 08-exceptions.c
147
148
149 Go to \ref GRAS_tut_tour_simpledata
150
151 */