From 2772ff2aa6e8bc7715318865b75d2dab91787787 Mon Sep 17 00:00:00 2001 From: mquinson Date: Sun, 16 Jul 2006 23:29:38 +0000 Subject: [PATCH 1/1] Lesson 8: exceptions git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@2598 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- doc/gtut-files/.cvsignore | 9 ++ doc/gtut-files/7-timers.output | 78 +++++++++--------- doc/gtut-files/8-exceptions.c | 85 +++++++++++++++++++ doc/gtut-files/8-exceptions.output | 45 ++++++++++ doc/gtut-files/Makefile | 33 +++++++- doc/gtut-tour-8-exceptions.doc | 127 ++++++++++++++++++++++++++++- 6 files changed, 333 insertions(+), 44 deletions(-) create mode 100644 doc/gtut-files/8-exceptions.c create mode 100644 doc/gtut-files/8-exceptions.output diff --git a/doc/gtut-files/.cvsignore b/doc/gtut-files/.cvsignore index 73be0370a8..7453afa401 100644 --- a/doc/gtut-files/.cvsignore +++ b/doc/gtut-files/.cvsignore @@ -60,3 +60,12 @@ _6-logs_simulator.c _7-timers_client.c _7-timers_server.c _7-timers_simulator.c + +8-exceptions.mk +8-exceptions.trace +8-exceptions_client +8-exceptions_server +8-exceptions_simulator +_8-exceptions_client.c +_8-exceptions_server.c +_8-exceptions_simulator.c diff --git a/doc/gtut-files/7-timers.output b/doc/gtut-files/7-timers.output index 152b70ac87..90ba2df4f8 100644 --- a/doc/gtut-files/7-timers.output +++ b/doc/gtut-files/7-timers.output @@ -1,55 +1,55 @@ $ ./test_server 12345 & ./test_client 127.0.0.1 12345 -[blaise:server:(23608) 0.000005] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 0.500361] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 1.003121] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 1.507935] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 2.010545] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 2.516219] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 3.018509] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 3.518713] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 4.022585] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. -[blaise:server:(23608) 4.482905] test.c:15: [test/CRITICAL] Argh, killed by 127.0.0.1:1024! Bye folks... -[blaise:server:(23608) 4.482930] gras/gras.c:79: [gras/INFO] Exiting GRAS -[blaise:client:(23611) 0.000005] test.c:99: [test/INFO] Programming the repetitive action with a frequency of 0.5 sec -[blaise:client:(23611) 0.000071] test.c:102: [test/INFO] Programming the delayed action in 5 secs -[blaise:client:(23611) 0.518553] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 1.020515] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 1.523454] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 2.027895] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 2.530948] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 3.035530] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 3.538912] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 4.038965] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 4.542989] test.c:66: [test/INFO] Hello sent to server -[blaise:client:(23611) 5.003026] test.c:73: [test/INFO] Kill sent to server -[blaise:client:(23611) 5.003056] test.c:78: [test/INFO] Break the client's while loop -[blaise:client:(23611) 5.003071] gras/gras.c:79: [gras/INFO] Exiting GRAS +[blaise:client:(1059) 0.000005] test.c:100: [test/INFO] Programming the repetitive action with a frequency of 0.5 sec +[blaise:client:(1059) 0.000059] test.c:103: [test/INFO] Programming the delayed action in 5 secs +[blaise:client:(1059) 0.503528] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 1.007421] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 1.518254] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 2.021273] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 2.523439] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 3.027624] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 3.531462] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 4.054546] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 4.555526] test.c:67: [test/INFO] Hello sent to server +[blaise:client:(1059) 5.003581] test.c:74: [test/INFO] Kill sent to server +[blaise:client:(1059) 5.003608] test.c:79: [test/INFO] Break the client's while loop +[blaise:client:(1059) 5.003625] gras/gras.c:79: [gras/INFO] Exiting GRAS +[blaise:server:(1056) 0.000005] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 0.504171] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 1.015021] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 1.517557] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 2.019864] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 2.524203] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 3.027500] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 3.551340] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 4.051570] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024. +[blaise:server:(1056) 4.499931] test.c:15: [test/CRITICAL] Argh, killed by 127.0.0.1:1024! Bye folks... +[blaise:server:(1056) 4.499955] gras/gras.c:79: [gras/INFO] Exiting GRAS $ $ ./test_simulator platform.xml test.xml -[Boivin:client:(2) 0.000000] test.c:99: [test/INFO] Programming the repetitive action with a frequency of 0.5 sec -[Boivin:client:(2) 0.000000] test.c:102: [test/INFO] Programming the delayed action in 5 secs -[Boivin:client:(2) 0.500537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 0.000000] test.c:100: [test/INFO] Programming the repetitive action with a frequency of 0.5 sec +[Boivin:client:(2) 0.000000] test.c:103: [test/INFO] Programming the delayed action in 5 secs +[Boivin:client:(2) 0.500537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 0.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 1.000537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 1.000537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 1.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 1.500537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 1.500537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 1.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 2.000537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 2.000537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 2.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 2.500537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 2.500537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 2.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 3.000537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 3.000537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 3.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 3.500537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 3.500537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 3.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 4.000537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 4.000537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 4.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 4.500537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 4.500537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 4.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 5.000537] test.c:66: [test/INFO] Hello sent to server +[Boivin:client:(2) 5.000537] test.c:67: [test/INFO] Hello sent to server [Jacquelin:server:(1) 5.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024. -[Boivin:client:(2) 5.001074] test.c:73: [test/INFO] Kill sent to server -[Boivin:client:(2) 5.001074] test.c:78: [test/INFO] Break the client's while loop +[Boivin:client:(2) 5.001074] test.c:74: [test/INFO] Kill sent to server +[Boivin:client:(2) 5.001074] test.c:79: [test/INFO] Break the client's while loop [Boivin:client:(2) 5.001074] gras/gras.c:79: [gras/INFO] Exiting GRAS [Jacquelin:server:(1) 5.001074] test.c:15: [test/CRITICAL] Argh, killed by Boivin:1024! Bye folks... [Jacquelin:server:(1) 5.001074] gras/gras.c:79: [gras/INFO] Exiting GRAS diff --git a/doc/gtut-files/8-exceptions.c b/doc/gtut-files/8-exceptions.c new file mode 100644 index 0000000000..fd3a407dbb --- /dev/null +++ b/doc/gtut-files/8-exceptions.c @@ -0,0 +1,85 @@ +#include + +XBT_LOG_NEW_DEFAULT_CATEGORY(test,"My little example"); + +typedef struct { + int killed; +} server_data_t; + + +int server_kill_cb(gras_msg_cb_ctx_t ctx, void *payload) { + gras_socket_t client = gras_msg_cb_ctx_from(ctx); + server_data_t *globals=(server_data_t*)gras_userdata_get(); + + CRITICAL2("Argh, killed by %s:%d! Bye folks, I'm out of here...", + gras_socket_peer_name(client), gras_socket_peer_port(client)); + + globals->killed = 1; + + return 1; +} /* end_of_kill_callback */ + +int server(int argc, char *argv[]) { + gras_socket_t mysock; /* socket on which I listen */ + server_data_t *globals; + + gras_init(&argc,argv); + + globals=gras_userdata_new(server_data_t*); + globals->killed=0; + + gras_msgtype_declare("kill", NULL); + gras_cb_register(gras_msgtype_by_name("kill"),&server_kill_cb); + + if (argc>1 && !strcmp(argv[1],"--cheat")) { + mysock = gras_socket_server(9999); + INFO0("Hi! hi! I'm not in the search range, but in 9999..."); + } else { + mysock = gras_socket_server((rand() % 10) + 3000); + INFO1("Ok, I'm hidden on port %d. Hope for the best.", gras_socket_my_port(mysock)); + } + + while (!globals->killed) { + gras_msg_handle(-1); /* blocking */ + } + + gras_exit(); + return 0; +} + +int client(int argc, char *argv[]) { + gras_socket_t mysock; /* socket on which I listen */ + gras_socket_t toserver; /* socket used to write to the server */ + int found; /* whether we found peer */ + int port; /* where we think that the server is */ + xbt_ex_t e; + + gras_init(&argc,argv); + + gras_msgtype_declare("kill", NULL); + mysock = gras_socket_server_range(1024, 10000, 0, 0); + + VERB0("Run little server, run. I'll get you. (sleep 1.5 sec)"); + gras_os_sleep(1.5); + + for (port=3000, found=0; port<3010 && !found; port++) { + TRY { + toserver = gras_socket_client(argv[1], port); + gras_msg_send(toserver,gras_msgtype_by_name("kill"), NULL); + gras_socket_close(toserver); + found = 1; + INFO1("Yeah! I found the server on %d! It's eradicated by now.",port); + } CATCH(e) { + xbt_ex_free(e); + } + if (!found) + INFO1("Damn, the server is not on %d",port); + } /* end_of_loop */ + + if(!found) + THROW0(not_found_error, 0, "Damn, I failed to find the server! I cannot survive this humilliation."); + + + gras_exit(); + return 0; +} diff --git a/doc/gtut-files/8-exceptions.output b/doc/gtut-files/8-exceptions.output new file mode 100644 index 0000000000..9a7652b042 --- /dev/null +++ b/doc/gtut-files/8-exceptions.output @@ -0,0 +1,45 @@ +$ ./test_server & ./test_client 127.0.0.1 +[blaise:server:(18660) 0.000005] test.c:39: [test/INFO] Ok, I'm hidden on port 3006. Hope for the best. +[blaise:server:(18660) 1.528036] test.c:15: [test/CRITICAL] Argh, killed by 127.0.0.1:1024! Bye folks, I'm out of here... +[blaise:server:(18660) 1.528059] gras/gras.c:79: [gras/INFO] Exiting GRAS +[blaise:client:(18664) 0.000005] test.c:76: [test/INFO] Damn, the server is not on 3000 +[blaise:client:(18664) 0.000128] test.c:76: [test/INFO] Damn, the server is not on 3001 +[blaise:client:(18664) 0.000190] test.c:76: [test/INFO] Damn, the server is not on 3002 +[blaise:client:(18664) 0.000250] test.c:76: [test/INFO] Damn, the server is not on 3003 +[blaise:client:(18664) 0.000308] test.c:76: [test/INFO] Damn, the server is not on 3004 +[blaise:client:(18664) 0.000368] test.c:76: [test/INFO] Damn, the server is not on 3005 +[blaise:client:(18664) 0.000535] test.c:81: [test/INFO] Yeah! I found the server on 3006! It's eradicated by now. +[blaise:client:(18664) 0.000553] gras/gras.c:79: [gras/INFO] Exiting GRAS +$ +$ ./test_server --cheat & ./test_client 127.0.0.1 +[blaise:client:(18706) 0.000005] test.c:76: [test/INFO] Damn, the server is not on 3000 +[blaise:client:(18706) 0.000130] test.c:76: [test/INFO] Damn, the server is not on 3001 +[blaise:client:(18706) 0.000192] test.c:76: [test/INFO] Damn, the server is not on 3002 +[blaise:client:(18706) 0.000251] test.c:76: [test/INFO] Damn, the server is not on 3003 +[blaise:client:(18706) 0.000309] test.c:76: [test/INFO] Damn, the server is not on 3004 +[blaise:client:(18706) 0.000368] test.c:76: [test/INFO] Damn, the server is not on 3005 +[blaise:client:(18706) 0.000426] test.c:76: [test/INFO] Damn, the server is not on 3006 +[blaise:client:(18706) 0.000485] test.c:76: [test/INFO] Damn, the server is not on 3007 +[blaise:client:(18706) 0.000543] test.c:76: [test/INFO] Damn, the server is not on 3008 +[blaise:client:(18706) 0.000601] test.c:76: [test/INFO] Damn, the server is not on 3009 +[blaise:client:(18706) 0.000631] xbt/ex.c:219: [xbt_ex/CRITICAL] Damn, I failed to find the server! I cannot survive this humilliation. +** SimGrid: UNCAUGHT EXCEPTION received on blaise(18706): category: not found; value: 0 +** Damn, I failed to find the server! I cannot survive this humilliation. +** Thrown by client() in this process + +** In client() at /home/mquinson/CVSIMPORT/gras/gras/doc/gtut-files/test.c:79 (static symbol) +** In main() at /home/mquinson/CVSIMPORT/gras/gras/doc/gtut-files/_test_client.c:21 (static symbol) +** In __libc_start_main() at ??:0 (dynamic symbol) +** In _start() at ../sysdeps/i386/elf/start.S:122 (static symbol) +$ killall test_server +[blaise:server:(18703) 0.000005] test.c:36: [test/INFO] Hi! hi! I'm not in the search range, but in 9999... +$ +$ ./test_simulator platform.xml test.xml +[Jacquelin:server:(1) 0.000000] test.c:39: [test/INFO] Ok, I'm hidden on port 3001. Hope for the best. +[Boivin:client:(2) 1.500000] test.c:76: [test/INFO] Damn, the server is not on 3000 +[Boivin:client:(2) 1.500537] test.c:81: [test/INFO] Yeah! I found the server on 3001! It's eradicated by now. +[Boivin:client:(2) 1.500537] gras/gras.c:79: [gras/INFO] Exiting GRAS +[Jacquelin:server:(1) 1.500537] test.c:15: [test/CRITICAL] Argh, killed by Boivin:1024! Bye folks, I'm out of here... +[Jacquelin:server:(1) 1.500537] gras/gras.c:79: [gras/INFO] Exiting GRAS +[1.500537] msg/global.c:475: [msg_kernel/INFO] Congratulations ! Simulation terminated : all processes are over +$ diff --git a/doc/gtut-files/Makefile b/doc/gtut-files/Makefile index 1331e0db73..8f8cadaff0 100644 --- a/doc/gtut-files/Makefile +++ b/doc/gtut-files/Makefile @@ -2,7 +2,8 @@ export LD_LIBRARY_PATH=$(GRAS_ROOT)/lib all: 1-bones.output 2-simple.output 3-args.output 4-callback.output \ - 5-globals.output 6-logs.output 7-timers.output + 5-globals.output 6-logs.output 7-timers.output 8-exceptions.output \ + veryclean: clean rm *.output* @@ -192,3 +193,33 @@ clean:: if [ -e 7-timers.mk ] ; then make -f 7-timers.mk clean; fi rm -f _7-timers_client.c _7-timers_server.c _7-timers_simulator.c 7-timers.trace 7-timers.mk +# Lesson 8: exceptions +######################################## + +8-exceptions.output: 8-exceptions_client 8-exceptions_server 8-exceptions_simulator + echo '$$ ./test_server & ./test_client 127.0.0.1 ' > $@ + ./8-exceptions_server 2>&1 |sed s/8-exceptions/test/ >> $@ 2>&1& + ./8-exceptions_client 127.0.0.1 2>&1 |sed s/8-exceptions/test/ >> $@ 2>&1 + sleep 1 + echo '$$' >> $@ + echo '$$ ./test_server --cheat & ./test_client 127.0.0.1 ' >> $@ + ./8-exceptions_server --cheat 2>&1 |sed s/8-exceptions/test/ >> $@ 2>&1& + ./8-exceptions_client 127.0.0.1 2>&1 |sed s/8-exceptions/test/ >> $@ 2>&1 + sleep 1 + echo '$$ killall test_server' >> $@ + killall 8-exceptions_server 8-exceptions_client 2>/dev/null || true + echo '$$' >> $@ + echo '$$ ./test_simulator platform.xml test.xml' >> $@ + ./8-exceptions_simulator gtut-platform.xml 3-args.xml 2>&1 |sed s/8-exceptions/test/ >> $@ 2>&1 + echo '$$' >> $@ + +8-exceptions_client 8-exceptions_server 8-exceptions_simulator: _8-exceptions_client.c _8-exceptions_server.c _8-exceptions_simulator.c + make -f 8-exceptions.mk + +_8-exceptions_client.c _8-exceptions_server.c _8-exceptions_simulator.c: 8-exceptions.c 3-args.xml + ../../tools/gras/gras_stub_generator 8-exceptions 3-args.xml >/dev/null + +clean:: + if [ -e 8-exceptions.mk ] ; then make -f 8-exceptions.mk clean; fi + rm -f _8-exceptions_client.c _8-exceptions_server.c _8-exceptions_simulator.c 8-exceptions.trace 8-exceptions.mk + 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 */ -- 2.20.1