diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-04-16 23:59:40 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-04-16 23:59:40 +0000 |
| commit | d1cbd26ded664bf2d3ace87036b822dedba28077 (patch) | |
| tree | b991c0196d5abe92d4d77e79449b44ced35b7d5f /src/include | |
| parent | 74be86847c8cdd274a274fc9384988cb81756d87 (diff) | |
Repair two places where SIGTERM exit could leave shared memory state
corrupted. (Neither is very important if SIGTERM is used to shut down the
whole database cluster together, but there's a problem if someone tries to
SIGTERM individual backends.) To do this, introduce new infrastructure
macros PG_ENSURE_ERROR_CLEANUP/PG_END_ENSURE_ERROR_CLEANUP that take care
of transiently pushing an on_shmem_exit cleanup hook. Also use this method
for createdb cleanup --- that wasn't a shared-memory-corruption problem,
but SIGTERM abort of createdb could leave orphaned files lying around.
Backpatch as far as 8.2. The shmem corruption cases don't exist in 8.1,
and the createdb usage doesn't seem important enough to risk backpatching
further.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/nbtree.h | 3 | ||||
| -rw-r--r-- | src/include/storage/ipc.h | 48 | ||||
| -rw-r--r-- | src/include/utils/elog.h | 9 |
3 files changed, 55 insertions, 5 deletions
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 1422994506d..ec3ac5fbf7a 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.117 2008/04/10 22:25:25 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.118 2008/04/16 23:59:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -574,6 +574,7 @@ extern void _bt_killitems(IndexScanDesc scan, bool haveLock); extern BTCycleId _bt_vacuum_cycleid(Relation rel); extern BTCycleId _bt_start_vacuum(Relation rel); extern void _bt_end_vacuum(Relation rel); +extern void _bt_end_vacuum_callback(int code, Datum arg); extern Size BTreeShmemSize(void); extern void BTreeShmemInit(void); diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index eb89f9a7dae..2123852bb73 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -11,21 +11,63 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/ipc.h,v 1.74 2008/01/01 19:45:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/storage/ipc.h,v 1.75 2008/04/16 23:59:40 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef IPC_H #define IPC_H +typedef void (*pg_on_exit_callback) (int code, Datum arg); + +/*---------- + * API for handling cleanup that must occur during either ereport(ERROR) + * or ereport(FATAL) exits from a block of code. (Typical examples are + * undoing transient changes to shared-memory state.) + * + * PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg); + * { + * ... code that might throw ereport(ERROR) or ereport(FATAL) ... + * } + * PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg); + * + * where the cleanup code is in a function declared per pg_on_exit_callback. + * The Datum value "arg" can carry any information the cleanup function + * needs. + * + * This construct ensures that cleanup_function() will be called during + * either ERROR or FATAL exits. It will not be called on successful + * exit from the controlled code. (If you want it to happen then too, + * call the function yourself from just after the construct.) + * + * Note: the macro arguments are multiply evaluated, so avoid side-effects. + *---------- + */ +#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg) \ + do { \ + on_shmem_exit(cleanup_function, arg); \ + PG_TRY() + +#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg) \ + cancel_shmem_exit(cleanup_function, arg); \ + PG_CATCH(); \ + { \ + cancel_shmem_exit(cleanup_function, arg); \ + cleanup_function (0, arg); \ + PG_RE_THROW(); \ + } \ + PG_END_TRY(); \ + } while (0) + /* ipc.c */ extern bool proc_exit_inprogress; extern void proc_exit(int code); extern void shmem_exit(int code); -extern void on_proc_exit(void (*function) (int code, Datum arg), Datum arg); -extern void on_shmem_exit(void (*function) (int code, Datum arg), Datum arg); +extern void on_proc_exit(pg_on_exit_callback function, Datum arg); +extern void on_shmem_exit(pg_on_exit_callback function, Datum arg); +extern void cancel_shmem_exit(pg_on_exit_callback function, Datum arg); extern void on_exit_reset(void); /* ipci.c */ diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 3b980cae79a..b7777e8f5f9 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.92 2008/03/24 18:08:47 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.93 2008/04/16 23:59:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -204,6 +204,13 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; * of levels this will work for. It's best to keep the error recovery * section simple enough that it can't generate any new errors, at least * not before popping the error stack. + * + * Note: an ereport(FATAL) will not be caught by this construct; control will + * exit straight through proc_exit(). Therefore, do NOT put any cleanup + * of non-process-local resources into the error recovery section, at least + * not without taking thought for what will happen during ereport(FATAL). + * The PG_ENSURE_ERROR_CLEANUP macros provided by storage/ipc.h may be + * helpful in such cases. *---------- */ #define PG_TRY() \ |
