diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2019-11-01 11:09:52 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2019-11-01 11:18:03 +0100 |
commit | 604bd3671121b51f977de146ed95484c2297fb3e (patch) | |
tree | 829045453c054befb9d795c33765501e2f4522f3 /src/include/utils/elog.h | |
parent | 73025140885c889410b9bfc4a30a3866396fc5db (diff) | |
download | postgresql-604bd3671121b51f977de146ed95484c2297fb3e.tar.gz postgresql-604bd3671121b51f977de146ed95484c2297fb3e.zip |
PG_FINALLY
This gives an alternative way of catching exceptions, for the common
case where the cleanup code is the same in the error and non-error
cases. So instead of
PG_TRY();
{
... code that might throw ereport(ERROR) ...
}
PG_CATCH();
{
cleanup();
PG_RE_THROW();
}
PG_END_TRY();
cleanup();
one can write
PG_TRY();
{
... code that might throw ereport(ERROR) ...
}
PG_FINALLY();
{
cleanup();
}
PG_END_TRY();
Discussion: https://www.postgresql.org/message-id/flat/95a822c3-728b-af0e-d7e5-71890507ae0c%402ndquadrant.com
Diffstat (limited to 'src/include/utils/elog.h')
-rw-r--r-- | src/include/utils/elog.h | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index ba0b7f6f79c..853c2e0709e 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -277,6 +277,25 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; * (sub)transaction abort. Failure to do so may leave the system in an * inconsistent state for further processing. * + * For the common case that the error recovery code and the cleanup in the + * normal code path are identical, the following can be used instead: + * + * PG_TRY(); + * { + * ... code that might throw ereport(ERROR) ... + * } + * PG_FINALLY(); + * { + * ... cleanup code ... + * } + * PG_END_TRY(); + * + * The cleanup code will be run in either case, and any error will be rethrown + * afterwards. + * + * You cannot use both PG_CATCH() and PG_FINALLY() in the same + * PG_TRY()/PG_END_TRY() block. + * * Note: while the system will correctly propagate any new ereport(ERROR) * occurring in the recovery section, there is a small limit on the number * of levels this will work for. It's best to keep the error recovery @@ -300,24 +319,33 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; */ #define PG_TRY() \ do { \ - sigjmp_buf *save_exception_stack = PG_exception_stack; \ - ErrorContextCallback *save_context_stack = error_context_stack; \ - sigjmp_buf local_sigjmp_buf; \ - if (sigsetjmp(local_sigjmp_buf, 0) == 0) \ + sigjmp_buf *_save_exception_stack = PG_exception_stack; \ + ErrorContextCallback *_save_context_stack = error_context_stack; \ + sigjmp_buf _local_sigjmp_buf; \ + bool _do_rethrow = false; \ + if (sigsetjmp(_local_sigjmp_buf, 0) == 0) \ { \ - PG_exception_stack = &local_sigjmp_buf + PG_exception_stack = &_local_sigjmp_buf #define PG_CATCH() \ } \ else \ { \ - PG_exception_stack = save_exception_stack; \ - error_context_stack = save_context_stack + PG_exception_stack = _save_exception_stack; \ + error_context_stack = _save_context_stack + +#define PG_FINALLY() \ + } \ + else \ + _do_rethrow = true; \ + { #define PG_END_TRY() \ } \ - PG_exception_stack = save_exception_stack; \ - error_context_stack = save_context_stack; \ + PG_exception_stack = _save_exception_stack; \ + error_context_stack = _save_context_stack; \ + if (_do_rethrow) \ + PG_RE_THROW(); \ } while (0) /* |