Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
280c279f6ac6628373756b62fb5fe5861d3adcd9
[simgrid.git] / src / xbt / ex.cpp
1 /* ex - Exception Handling                                                  */
2
3 /* Copyright (c) 2005-2018. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include <cstdio>
9 #include <cstdlib>
10
11 #include <xbt/backtrace.hpp>
12 #include "src/internal_config.h"           /* execinfo when available */
13 #include "xbt/ex.h"
14 #include <xbt/ex.hpp>
15 #include "xbt/log.h"
16 #include "xbt/log.hpp"
17 #include "xbt/backtrace.h"
18 #include "xbt/backtrace.hpp"
19 #include "src/xbt_modinter.h"       /* backtrace initialization headers */
20
21 #include "simgrid/sg_config.hpp" /* Configuration mechanism of SimGrid */
22
23 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex, xbt, "Exception mechanism");
24
25 // DO NOT define ~xbt_ex() in ex.hpp.
26 // Defining it here ensures that xbt_ex is defined only in libsimgrid, but not in libsimgrid-java.
27 // Doing otherwise naturally breaks things (at least on freebsd with clang).
28
29 xbt_ex::~xbt_ex() = default;
30
31 void _xbt_throw(char* message, xbt_errcat_t errcat, int value, const char* file, int line, const char* func)
32 {
33   xbt_ex e(simgrid::xbt::ThrowPoint(file, line, func), message);
34   xbt_free(message);
35   e.category = errcat;
36   e.value = value;
37   throw e;
38 }
39
40 /** @brief shows an exception content and the associated stack if available */
41 void xbt_ex_display(xbt_ex_t * e)
42 {
43   simgrid::xbt::logException(xbt_log_priority_critical, "UNCAUGHT EXCEPTION", *e);
44 }
45
46 /** \brief returns a short name for the given exception category */
47 const char *xbt_ex_catname(xbt_errcat_t cat)
48 {
49   switch (cat) {
50   case unknown_error:
51     return "unknown error";
52   case arg_error:
53     return "invalid argument";
54   case bound_error:
55     return "out of bounds";
56   case mismatch_error:
57     return "mismatch";
58   case not_found_error:
59     return "not found";
60   case system_error:
61     return "system error";
62   case network_error:
63     return "network error";
64   case timeout_error:
65     return "timeout";
66   case cancel_error:
67     return "action canceled";
68   case thread_error:
69     return "thread error";
70   case host_error:
71     return "host failed";
72   case tracing_error:
73     return "tracing error";
74   case io_error:
75     return "io error";
76   case vm_error:
77     return "vm error";
78   default:
79     return "INVALID ERROR";
80   }
81   return "INVALID ERROR";
82 }
83
84 #ifdef SIMGRID_TEST
85 #include "xbt/ex.h"
86 #include <cstdio>
87 #include <xbt/ex.hpp>
88
89 XBT_TEST_SUITE("xbt_ex", "Exception Handling");
90
91 XBT_TEST_UNIT("controlflow", test_controlflow, "basic nested control flow")
92 {
93   xbt_ex_t ex;
94   int n = 1;
95
96   xbt_test_add("basic nested control flow");
97
98   try {
99     if (n != 1)
100       xbt_test_fail("M1: n=%d (!= 1)", n);
101     n++;
102     try {
103       if (n != 2)
104         xbt_test_fail("M2: n=%d (!= 2)", n);
105       n++;
106       THROWF(unknown_error, 0, "something");
107     }
108     catch (xbt_ex& ex) {
109       if (n != 3)
110         xbt_test_fail("M3: n=%d (!= 3)", n);
111       n++;
112     }
113     n++;
114     try {
115       if (n != 5)
116         xbt_test_fail("M2: n=%d (!= 5)", n);
117       n++;
118       THROWF(unknown_error, 0, "something");
119     }
120     catch(xbt_ex& ex){
121       if (n != 6)
122         xbt_test_fail("M3: n=%d (!= 6)", n);
123       n++;
124       throw;
125       n++;
126     }
127     xbt_test_fail("MX: n=%d (shouldn't reach this point)", n);
128   }
129   catch(xbt_ex& e) {
130     if (n != 7)
131       xbt_test_fail("M4: n=%d (!= 7)", n);
132     n++;
133   }
134   if (n != 8)
135     xbt_test_fail("M5: n=%d (!= 8)", n);
136 }
137
138 XBT_TEST_UNIT("value", test_value, "exception value passing")
139 {
140   try {
141     THROWF(unknown_error, 2, "toto");
142   }
143   catch (xbt_ex& ex) {
144     xbt_test_add("exception value passing");
145     if (ex.category != unknown_error)
146       xbt_test_fail("category=%d (!= 1)", (int)ex.category);
147     if (ex.value != 2)
148       xbt_test_fail("value=%d (!= 2)", ex.value);
149     if (strcmp(ex.what(), "toto"))
150       xbt_test_fail("message=%s (!= toto)", ex.what());
151   }
152 }
153
154 XBT_TEST_UNIT("variables", test_variables, "variable value preservation")
155 {
156   xbt_ex_t ex;
157   int r1;
158   XBT_ATTRIB_UNUSED int r2;
159   int v1;
160   int v2;
161
162   r1 = r2 = v1 = v2 = 1234;
163   try {
164     r2 = 5678;
165     v2 = 5678;
166     THROWF(unknown_error, 0, "toto");
167   }
168   catch(xbt_ex& e) {
169     xbt_test_add("variable preservation");
170     if (r1 != 1234)
171       xbt_test_fail("r1=%d (!= 1234)", r1);
172     if (v1 != 1234)
173       xbt_test_fail("v1=%d (!= 1234)", v1);
174     /* r2 is allowed to be destroyed because not volatile */
175     if (v2 != 5678)
176       xbt_test_fail("v2=%d (!= 5678)", v2);
177   }
178 }
179
180 XBT_TEST_UNIT("cleanup", test_cleanup, "cleanup handling")
181 {
182   int v1;
183   int c;
184
185   xbt_test_add("cleanup handling");
186
187   v1 = 1234;
188   c = 0;
189   try {
190     v1 = 5678;
191     THROWF(1, 2, "blah");
192   }
193   catch (xbt_ex& ex) {
194     if (v1 != 5678)
195       xbt_test_fail("v1 = %d (!= 5678)", v1);
196     c = 1;
197     if (v1 != 5678)
198       xbt_test_fail("v1 = %d (!= 5678)", v1);
199     if (not(ex.category == 1 && ex.value == 2 && not strcmp(ex.what(), "blah")))
200       xbt_test_fail("unexpected exception contents");
201   }
202   if (not c)
203     xbt_test_fail("xbt_ex_free not executed");
204 }
205 #endif                          /* SIMGRID_TEST */