summaryrefslogtreecommitdiff
path: root/TAO/docs/exceptions.html
blob: da2d41f7541a6badf96d239fcdf70098524c835f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
<!DOCTYPE HTML SYSTEM
"http://www.w3.org/pub/WWW/MarkUp/Cougar/Cougar.dtd">
<!-- $Id$ -->
<html> <head>
<title>Writing exception safe codes</title>
</head>

<body>
<h1>Writing exception safe codes</h1>

TAO can be use on platforms with/without native exception support.
However, there are certain guidelines that need to be followed in
order for it to work on both platforms.

<h3>In a Nutshell</h3>

This section explains some simple rules of writing programs for
platforms with and without native exception support using TAO's try
macros.

<ol>
  <li><em>Function definition:</em><br>
      A function that throws exceptions or calls other exception
      throwing functions must have an argument of reference of
      <code>CORBA_Environment</code> for exceptions be passed back
      thru it.  This arguemnt should <em>always</em> be named
      <code>TAO_IN_ENV</code> (which means the passed in environment,)
      and has a default value of
      <code>CORBA_Environment::default_environment ()</code>.  For
      example,<p>

      <pre>
      int foobar (int a, int b, CORBA_Environment &TAO_IN_ENV =
                                  CORBA_Environment::default_environment);
      </pre><p>

  <li><em>Throwing exceptions:</em><br>
      Use <code>TAO_THROW</code> and <code>TAO_THROW_RETURN</code> to
      throw exceptions.

  <li><em>Propagating exceptions:</em><br>
      To simulate native exceptions on platforms without native
      exceptions, <em>every</em> single function call that may throw
      exceptions must be followed by <code>TAO_CHECK_RETURN</code> or
      <code>TAO_CHECK_RETURN_VOID</code>.<p>

      You should pass <code>TAO_IN_ENV</code> to these functions.<p>

      Be very careful not to combine calls to several exception
      throwing functions in one statement.<p>

  <li><em>Catching exceptions:</em><br>
      Use <code>TAO_TRY</code> and buddies to catch exceptions.<p>
      <ul>
        <li>Within a <code>TAO_TRY</code> block, use the variable
            <code>TAO_TRY_ENV</code> to pass down the
            <code>CORBA_Environment</code> (see <a
            href="#try_env">this</a> example.) <p>

        <li>Follow <em>every</em> exception throwing function with
            <code>TAO_CHECK_ENV</code>. <p>

        <li>Use <code>TAO_CATCH</code> to catch exceptions of certain
            type. <p>

        <li><code>TAO_CATCHANY</code> catches <em>any</em> exceptions
            of type <code>CORBA_Exception</code>.<p>

        <li>Use <code>TAO_RETHROW</code> to rethrow the same exception
            within a <code>TAO_CATCH</code> or
            <code>TAO_CATCHANY</code> block.<p>

        <li>A <code>TAO_TRY</code> block must be terminated with a
            <code>TAO_ENDTRY</code> statement.<p>

        <li>Throw an exception within a <code>TAO_TRY</code> block
            using <a href="#try_throw"><code>TAO_TRY_THROW</code></a><p>

        <li>Notice that at the moment, <code>TAO_TRY</code> macros do
            not propogate the exception up if one is not caught.<p>

      </ul><p>

  <li>Avoid using macros that require to specify the environment used
      like, <code>TAO_THROW_ENV_RETURN</code>,
      <code>TAO_CHECK_ENV_RETURN</code> and so on.  They will be
      depricated in the future.
</ol>

<h3>Details</h3>

Refer to <code>$TAO_ROOT/tao/try_macros.h</code> for complete
definitions of macros discussed here.

<ul>
  <li>Use <code>TAO_THROW</code>, <code>TAO_THROW_ENV</code>,
      <code>TAO_THROW_RETURN</code>, <code>TAO_THROW_ENV_RETURN</code>
      to throw exceptions. <code>TAO_THROW</code> and
      <code>TAO_THROW_RETURN</code> assume that the name of the
      <code>CORBA_Environment</code> variable used to pass back the
      exception is called <code>_env</code>. Use
      <code>TAO_THROW_ENV</code> and <code>TAO_THROW_ENV_RETURN</code>
      to pass back thru the <code>CORBA_Environment</code> variable
      specified.  (Also see: <a href="#try_throw">Throwing exceptions
      within try blocks.</a>)<p>

  <li><a name="try_env"></a>Use <code>TAO_TRY</code>,
      <code>TAO_CHECK_ENV</code>, <code>TAO_CATCH</code>,
      <code>TAO_CATCHANY</code>, and <code>TAO_ENDTRY</code>
      macros. For example:<br>

<pre>
      TAO_TRY
        {
          some_operation (arg1, arg2, TAO_TRY_ENV);
          TAO_CHECK_ENV;

          some_other_operation (arg1, arg2, arg3, TAO_TRY_ENV);
          TAO_CHECK_ENV;
        }
      TAO_CATCH (CORBA_some_exception, ex)
        {
          // error handling.
        }
      TAO_CATCHANY
        {
          // error handling.
        }
      TAO_ENDTRY;
</pre><br>

      Since a lot of compilers/platforms still don't handle native
      exceptions correctly, TAO doesn't use exceptions on these
      platforms and tend to check the returning environment.  When
      these programs move to platforms that support native exceptions,
      they stop working.<p>

  <li><code>TAO_TRY</code> defines a new
      <code>CORBA_Environment</code> called TAO_TRY_ENV and use it to
      pass down the functions it guards against.  If you want to reuse
      the <code>CORBA_Environment</code> that's alreday defined in the
      scope <code>TAO_TRY</code> resides, you can use
      <code>TAO_TRY_VAR</code> to achieve that.<p>

  <li><code>TAO_TRY</code> also declares a label.  To avoid defining the
      same label multiple times within a function, use
      <code>TAO_TRY_EX</code>, <code>TAO_CHECK_ENV_EX</code> with
      different labels for different try blocks instead.  For
      example,<br>

<pre>
      TAO_TRY_EX (block_1)
        {
          some_operation (arg1, arg2, TAO_TRY_ENV);
          TAO_CHECK_ENV_EX (block_1);

          some_other_operation (arg1, arg2, arg3, TAO_TRY_ENV);
          TAO_CHECK_ENV_EX (block_1);
        }
      TAO_CATCH (CORBA_some_exception, ex)
        {
          // error handling.
        }
      TAO_CATCHANY
        {
          // error handling.
        }
      TAO_ENDTRY;

      // Some other operation here
      //       .
      //       .
      //       .
      //       .

      TAO_TRY_EX (block_2)
        {
          foo (arg, TAO_TRY_ENV);
          TAO_CHECK_ENV_EX (block_2);

          bar (arg1, arg2, TAO_TRY_ENV);
          TAO_CHECK_ENV_EX (block_2);
        }
      TAO_CATCH (CORBA_some_exception, ex)
        {
          // error handling.
        }
      TAO_CATCHANY
        {
          // error handling.
        }
      TAO_ENDTRY;
</pre><p>

      <a name="try_throw"></a>
  <li>Notice that you need to use <code>TAO_TRY_THROW</code> and
      <code>TAO_TRY_THROW_EX</code> when throwing exceptions within
      the try block.  Without using it, the exception won't be caught
      by the try block, which is not how native exceptions work.<p>

  <li>Follow each operation that may throw an exception with
      <code>TAO_CHECK_ENV</code> or <code>TAO_CHECK_ENV_EX</code>.
      This is required for simulated exceptions to break out of
      current flow of control into <code>TAO_CATCH</code>
      sections. Although it is not required to put an
      <code>TAO_CHECK_ENV</code> or an <code>TAO_CHECK_ENV_EX</code>
      after the last operation, it is much cleaner to always put it
      there and avoid further errors when you need add more stuff
      after that.<p>

  <li>TAO functions use a <code>CORBA_Environment</code> argument to
      pass in/out the simulated exceptions.  By default, this argument
      is named "<code>_env</code>" (which is what TAO_IDL generated
      code uses.)  Use <code>TAO_THROW</code> or
      <code>TAO_THROW_RETURN</code> to throw an exception.  However,
      if a function uses a different name to pass back the CORBA
      environment, you'll need to use <code>TAO_THROW_ENV</code> or
      <code>TAO_THROW_ENV_RETURN</code> and specify the name of the
      variable used to pass back the CORBA environment.<p>

  <li>To rethrow an exception after catching it, use
      <code>TAO_RETHROW_RETURN</code> or
      <code>TAO_RETHROW_RETURN_VOID</code>.  But if you are reusing
      the same <code>CORBA::Environment</code> variable of the
      function in the try block, use
      <code>TAO_RETHROW_SAME_ENV_RETURN</code> and
      <code>TAO_RETHROW_SAME_ENV_RETURN_VOID</code> instead.<p>

  <li>Follow each statement that throws exceptions with
      <code>TAO_CHECK_ENV_RETURN</code>,
      <code>TAO_CHECK_ENV_RETURN_VOID</code> when these exceptions are
      not to be caught in the current subroutine.  Likewise,
      <code>TAO_CHECK_ENV_PRINT_RETURN</code> and
      <code>TAO_CHECK_ENV_PRINT_RETURN_VOID</code> pass back an
      exception after printing out the content.  Notice that the
      printing will not work on platforms where native exceptions are
      supported.  If you have to print out exceptions, you <em>have
      to</em> catch them.  All these macros cannot and should not be
      used in a <code>TRY</code> block.<p>

  <li><code>TAO_GUARD_THROW</code>,
      <code>TAO_GUARD_THROW_RETURN</code>,
      <code>TAO_READ_GUARD_THROW</code>,
      <code>TAO_READ_GUARD_THROW_RETURN</code>,
      <code>TAO_WRITE_GUARD_THROW</code>, and
      <code>TAO_WRITE_GUARD_THROW_RETURN</code> try to acquire a lock
      and throw the specified exception when it fails to acquire the
      lock.<p>

  <li>Notice that <code>TAO_CATCHANY</code> catches <em>any</em>
      <code>CORBA_Exception</code> or its subclasses.  This limited
      catch behavior makes TAO programs behave the same on platforms
      with or without native exceptions.  If there're needs to catch
      all native exceptions in your program, use
      <code>TAO_CATCHALL</code> instead. <p>

  <li>Be <em>VERY</em> wary of <code>TAO_CATCHALL</code>.  It catches
      exceptions of any type.  If your program depends on it, then,
      more often than not, there're something wrong with it.<p>

  <li>Use <code>auto_prt</code> type mechanism to prevent memory leaks
      from exceptions.<p>

  <li>Don't catch an exception just to rethrow it.  Exceptions cost
      you performance.<p>

  <li>Current implementation of <code>TAO_TRY/TAO_CATCH</code> macros
      do not propagate a exception up if it is not caught.  (So,
      you'll have to catch all exceptions with a
      <code>TAO_CATCHANY</code> and rethrow it, which contradicts the
      previous guideline. ;( )<p>

</ul>

<h2>TO-DO</h2>
<ol>
  <li>Automatic rethrow simpulated exceptions if not caught?
  <li>must check if the same exception can be caught twice on
      compilers without c++ exceptions.
</ol>

<h3>General Guidelines of Exceptions</h3>
<ul>
  <li>When exceptions occur, make sure an object's is still in
      a valid state or change to a state that can be safely
      destructed.<p>

  <li>Watch out for side effect in the expression which may cause
      exceptions.  In the following example, what should
      <code>i</code> be if an exception does occur?<br>
<pre>
      TAO_TRY
        {
            obj[i++] = foo_bar_method (a, b, TAO_TRY_ENV);
        }
</pre><p>

  <li>Make sure an exception doesn't cause resource leak (memory,
      socket, ...) (hint: Use auto_ptr to avoid memory leak.)<p>

  <li>Don't catch any exception that you don't know how to handle.<p>

  <li>Never throw an exception from destructor (unless you know what
      it implies.)<p>

  <li>Use exceptions to provide more information about the error.<p>

  <li>Rethrow a different exception only to provide <em>more</em>
      information.  Do not catch an exception just to rethrow, say,
      <code>unknow_exception</code>.<p>

</ul>
<!--#include virtual="/~schmidt/cgi-sig.html" -->
</body></HTML>