Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[trace] remove repeated parameter, plus add new test for tracing by MSG process
[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 }
58 CATCH(e) {
59   /* error handling code */
60 } \endverbatim
61
62 Another strange thing is that you should actually free the memory allocated
63 to the exception with xbt_ex_fres() if you manage to deal with them. There
64 is a bit more than this on the picture (#TRY_CLEANUP blocks, for example), and
65 you should check the section \ref XBT_ex for more details.
66
67 You should be <b>very carfull</b> when using the exceptions. They work great
68 when used correctly, but there is a few golden rules you should never break.
69 Moreover, the error messages and symptom can get <b>really crude</b> when
70 misusing the exceptions.
71
72  - <b>Do not move out of a TRY block with a return, a break or any other
73    kind of jump. NEVER. EVER.</b>. This is the most tempting error, and this
74    drives the system nuts. You will probably segfault in the next exception
75    raising, far away from where you incidentally typed <tt>return</tt>
76    (this is because there is some cleanups to do at the end of a TRY block,
77    you cannot just leave it).
78  - <b>Play safe with variables modified in the TRY block</b>. You may want
79    to mark them as <tt>volatile</tt>, which is a modifier (just like
80    <tt>const</tt>) indicating that the value of the denoted variable may get
81    changed by external parts of the program during the run. This is the case
82    when your data gets modified by an exception raising function, I guess.
83
84 So, as you can see, you don't want to include large sections of your program
85 in TRY blocks. If you do so, it's quite sure that one day, you'll do a break
86 or a return within this block. And believe me, finding such typos is a real
87 pain. 
88
89 If you are suspecting this kind of error, I made a little script for you:
90 check <tt>tools/xbt_exception_checker</tt> from the CVS. Given a set of C
91 files, it extracts the TRY blocks and display them on the standard output so
92 that you can grep for <tt>return</tt>, <tt>break</tt> and such forbidden
93 words.
94
95 \section GRAS_tut_tour_exceptions_use Putting exceptions into action
96
97 Okay. I hope those little warnings didn't discourage you from using the
98 exceptions, because they really are a nice mecanism. We will now change a
99 bit our program to take advantage of them. The only issue is that when a
100 program run properly, it usually don't raise any exception. We could protect
101 the calls we already have with exception handling, but it wouldn't be really
102 exciting since we know this code does not throw any exception under the
103 condition we use (actually, most of the GRAS functions may throw exception
104 on problem).
105
106 Instead, we will code a little game between the client and the server. We
107 won't tell the client the exact port on which the server listen, and it will
108 have to find from itself. For this, it will try to open socket and send the
109 kill message to each ports of the search range. If it manage to close the
110 socket after sending the message without being interrupted by an exception,
111 it can assume that it killed the server and stop searching.
112 \dontinclude 08-exceptions.c
113 \skip port=3000
114 \until end_of_loop
115
116 To make the game a bit more fun (and to show you what an exception actually
117 look like when it's not catched), we add a potential command line argument
118 to the server, asking it to cheat and to not open its port within the search
119 range but elsewhere:
120 \dontinclude 08-exceptions.c
121 \skip strcmp
122 \until gras_socket_my_port
123 \until }
124
125 Then, when the client detects that it didn't manage to find&destroy the
126 server, it throws a suicide exception (sorry for the bad jokes):
127 \skip if(!found)
128 \until THROW
129
130 \section GRAS_tut_tour_exceptions_recap Recapping everything together
131
132 Here is the output produced by this new program. Note that when the program
133 bails out because of an uncatched exception, it displays its backtrace just
134 like a JVM would do (ok, it'a a bit cruder than the one of the JVM, but
135 anyway). For each function frame of the calling stack, it displays the
136 function name and its location in the source files (if it manage to retrieve
137 it). Don't be jalous, you can display such stacks wherever you want with 
138 xbt_backtrace_display() ;)
139
140 Unfortunately, this feature is only offered under Linux for now since I have
141 no idea of how to retrieve the call stack of the current process under the
142 other operating systems. But help is always welcome in this area too ;)
143
144 \include 08-exceptions.output
145
146 The complete program reads:
147 \include 08-exceptions.c
148
149
150 Go to \ref GRAS_tut_tour_simpledata
151
152 */