X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/7fdd9d11419684606beb08a8a7bc673955eb08af..b47649fd1bd845d7c3d4c07e4400382570d080db:/doc/gtut-tour-8-exceptions.doc diff --git a/doc/gtut-tour-8-exceptions.doc b/doc/gtut-tour-8-exceptions.doc index 118ef2616d..260b5c3e5b 100644 --- a/doc/gtut-tour-8-exceptions.doc +++ b/doc/gtut-tour-8-exceptions.doc @@ -1,5 +1,5 @@ /** -@page GRAS_tut_tour_exceptions Lesson 8: Handling errors through exceptions (TODO) +@page GRAS_tut_tour_exceptions Lesson 8: Handling errors through exceptions \section GRAS_tut_tour_exceptions_toc Table of Contents - \ref GRAS_tut_tour_exceptions_intro @@ -10,17 +10,136 @@ \section GRAS_tut_tour_exceptions_intro Introduction +Exceptions are a great mecanism to deal with error exception, everyone knows +that. + +Without exceptions, you have to rely on returning a value indicating whether +the function call were right or not, and check the return values of every +single function you call. If there is one point in the calling sequence +where your forgot this check, the chain is broken and caller won't notice +the issue. In practice, dealing with error without exceptions loads user +code with *tons* of those stupid checks and you loose your functional code +in the middle of that miasm. + +With them, you simply write your code. If you want to deal with errors (ie, +you actually know how to react to errors at this point of your code), you +write a catching block. If you don't, you don't. And exceptions flow through +from trowing point to catching point without bothering you. + +At this point, you may be a bit surprised by the previous paragraphs. +SimGrid and GRAS are written in C, and everybody knows that there is no +exception in C but only in C++, Java and such. This is true, exceptions are +not part of the C language, but this is such a great tool that we +implemented an exception mecanism as part of the SimGrid library (with +setjmp and longjmp, for the curious). + +Being "home-grown" make our exception mecanic both stronger and weaker at +the same time. First it is weaker because, well, we are more limitated +within the library as we are than if we could change the compiler itself to +add some extra checks here and specific treatment there. But it is also a +advantage for us, since the exception mecanism is perfectly fitted to the +distributed settings of GRAS processes. They can easily propagate on the +net, as we will see in the next lesson (\ref GRAS_tut_tour_rpc) and contain +information about the host on which they were thrown (#xbt_ex_t) along with +the thrown point in the source code. + +The syntax of XBT exceptions should not sound unfamilliar to most of you. +You throw them using the #THROW0...#THROW7 macros. They take 2 extra +arguments in addition to the format and its self arguments: an error +category (of type #xbt_errcat_t) and an error "value" (an integer; +pratically, this is often left to 0 in my own code). So, you may have +something like the following: +\verbatim THROW3(system_error, 0, "Cannot connect to %s:%d because of %s", hostname, port, reason);\endverbatim + +Then, you simply add a #TRY/#CATCH block around your code: +\verbatim TRY{ + /* your code */ +} CATCH(e) { + /* error handling code */ +} \endverbatim + +Another strange thing is that you should actually free the memory allocated +to the exception with xbt_ex_fres() if you manage to deal with them. There +is a bit more than this on the picture (#CLEANUP blocks, for example), and +you should check the section \ref XBT_ex for more details. + +You should be very carfull when using the exceptions. They work great +when used correctly, but there is a few golden rules you should never break. +Moreover, the error messages and symptom can get really crude when +misusing the exceptions. + + - Do not move out of a TRY block with a return, a break or any other + kind of jump. NEVER. EVER.. This is the most tempting error, and this + drives the system nuts. You will probably segfault in the next exception + raising, far away from where you incidentally typed return + (this is because there is some cleanups to do at the end of a TRY block, + you cannot just leave it). + - Play safe with variables modified in the TRY block. You may want + to mark them as volatile, which is a modifier (just like + const) indicating that the value of the denoted variable may get + changed by external parts of the program during the run. This is the case + when your data gets modified by an exception raising function, I guess. + +So, as you can see, you don't want to include large sections of your program +in TRY blocks. If you do so, it's quite sure that one day, you'll do a break +or a return within this block. And believe me, finding such typos is a real +pain. + \section GRAS_tut_tour_exceptions_use Putting exceptions into action +Okay. I hope those little warnings didn't discourage you from using the +exceptions, because they really are a nice mecanism. We will now change a +bit our program to take advantage of them. The only issue is that when a +program run properly, it usually don't raise any exception. We could protect +the calls we already have with exception handling, but it wouldn't be really +exciting since we know this code does not throw any exception under the +condition we use (actually, most of the GRAS functions may throw exception +on problem). + +Instead, we will code a little game between the client and the server. We +won't tell the client the exact port on which the server listen, and it will +have to find from itself. For this, it will try to open socket and send the +kill message to each ports of the search range. If it manage to close the +socket after sending the message without being interrupted by an exception, +it can assume that it killed the server and stop searching. +\dontinclude 8-exceptions.c +\skip port=3000 +\until end_of_loop + +To make the game a bit more fun (and to show you what an exception actually +look like when it's not catched), we add a potential command line argument +to the server, asking it to cheat and to not open its port within the search +range but elsewhere: +\dontinclude 8-exceptions.c +\skip strcmp +\until gras_socket_my_port +\until } + +Then, when the client detects that it didn't manage to find&destroy the +server, it throws a suicide exception (sorry for the bad jokes): +\skip if(!found) +\until THROW \section GRAS_tut_tour_exceptions_recap Recapping everything together -The program now reads: -\include 8-exceptions.c +Here is the output produced by this new program. Note that when the program +bails out because of an uncatched exception, it displays its backtrace just +like a JVM would do (ok, it'a a bit cruder than the one of the JVM, but +anyway). For each function frame of the calling stack, it displays the +function name and its location in the source files (if it manage to retrieve +it). Don't be jalous, you can display such stacks wherever you want with +xbt_backtrace_display() ;) + +Unfortunately, this feature is only offered under Linux for now since I have +no idea of how to retrieve the call stack of the current process under the +other operating systems. But help is always welcome in this area too ;) -Which produces the expected output: \include 8-exceptions.output +The complete program reads: +\include 8-exceptions.c + + Go to \ref GRAS_tut_tour_rpc */