diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-04-16 23:59:51 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-04-16 23:59:51 +0000 |
commit | d5249bb409ed3f13602bfa24b4c48acedd8783ec (patch) | |
tree | b49a0c0abc11c5785e848224e011777906041234 /src/backend/access | |
parent | 95b7a876f6cc29f871a9cae0d66cea91bb76b504 (diff) | |
download | postgresql-d5249bb409ed3f13602bfa24b4c48acedd8783ec.tar.gz postgresql-d5249bb409ed3f13602bfa24b4c48acedd8783ec.zip |
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/backend/access')
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 17 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtutils.c | 18 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 32 |
3 files changed, 38 insertions, 29 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 5cfa8f315d7..d547b910528 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.156 2008/01/01 19:45:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.156.2.1 2008/04/16 23:59:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,7 @@ #include "catalog/index.h" #include "commands/vacuum.h" #include "storage/freespace.h" +#include "storage/ipc.h" #include "storage/lmgr.h" #include "utils/memutils.h" @@ -538,21 +539,15 @@ btbulkdelete(PG_FUNCTION_ARGS) stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult)); /* Establish the vacuum cycle ID to use for this scan */ - PG_TRY(); + /* The ENSURE stuff ensures we clean up shared memory on failure */ + PG_ENSURE_ERROR_CLEANUP(_bt_end_vacuum_callback, PointerGetDatum(rel)); { cycleid = _bt_start_vacuum(rel); btvacuumscan(info, stats, callback, callback_state, cycleid); - - _bt_end_vacuum(rel); - } - PG_CATCH(); - { - /* Make sure shared memory gets cleaned up */ - _bt_end_vacuum(rel); - PG_RE_THROW(); } - PG_END_TRY(); + PG_END_ENSURE_ERROR_CLEANUP(_bt_end_vacuum_callback, PointerGetDatum(rel)); + _bt_end_vacuum(rel); PG_RETURN_POINTER(stats); } diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 6f88a34488e..3db75d4b992 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.88 2008/01/01 19:45:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.88.2.1 2008/04/16 23:59:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1252,8 +1252,11 @@ _bt_vacuum_cycleid(Relation rel) /* * _bt_start_vacuum --- assign a cycle ID to a just-starting VACUUM operation * - * Note: the caller must guarantee (via PG_TRY) that it will eventually call - * _bt_end_vacuum, else we'll permanently leak an array slot. + * Note: the caller must guarantee that it will eventually call + * _bt_end_vacuum, else we'll permanently leak an array slot. To ensure + * that this happens even in elog(FATAL) scenarios, the appropriate coding + * is not just a PG_TRY, but + * PG_ENSURE_ERROR_CLEANUP(_bt_end_vacuum_callback, PointerGetDatum(rel)) */ BTCycleId _bt_start_vacuum(Relation rel) @@ -1338,6 +1341,15 @@ _bt_end_vacuum(Relation rel) } /* + * _bt_end_vacuum wrapped as an on_shmem_exit callback function + */ +void +_bt_end_vacuum_callback(int code, Datum arg) +{ + _bt_end_vacuum((Relation) DatumGetPointer(arg)); +} + +/* * BTreeShmemSize --- report amount of shared memory space needed */ Size diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index d2075018d96..d0cce7f210e 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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/backend/access/transam/xlog.c,v 1.292 2008/01/21 11:17:46 petere Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.292.2.1 2008/04/16 23:59:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,6 +43,7 @@ #include "postmaster/bgwriter.h" #include "storage/bufpage.h" #include "storage/fd.h" +#include "storage/ipc.h" #include "storage/pmsignal.h" #include "storage/procarray.h" #include "storage/smgr.h" @@ -420,11 +421,11 @@ static void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, static void WriteControlFile(void); static void ReadControlFile(void); static char *str_time(pg_time_t tnow); -static void issue_xlog_fsync(void); - #ifdef WAL_DEBUG static void xlog_outrec(StringInfo buf, XLogRecord *record); #endif +static void issue_xlog_fsync(void); +static void pg_start_backup_callback(int code, Datum arg); static bool read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *minRecoveryLoc); static void rm_redo_error_callback(void *arg); @@ -6445,8 +6446,8 @@ pg_start_backup(PG_FUNCTION_ARGS) XLogCtl->Insert.forcePageWrites = true; LWLockRelease(WALInsertLock); - /* Use a TRY block to ensure we release forcePageWrites if fail below */ - PG_TRY(); + /* Ensure we release forcePageWrites if fail below */ + PG_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) 0); { /* * Force a CHECKPOINT. Aside from being necessary to prevent torn @@ -6518,16 +6519,7 @@ pg_start_backup(PG_FUNCTION_ARGS) errmsg("could not write file \"%s\": %m", BACKUP_LABEL_FILE))); } - PG_CATCH(); - { - /* Turn off forcePageWrites on failure */ - LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); - XLogCtl->Insert.forcePageWrites = false; - LWLockRelease(WALInsertLock); - - PG_RE_THROW(); - } - PG_END_TRY(); + PG_END_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) 0); /* * We're done. As a convenience, return the starting WAL location. @@ -6539,6 +6531,16 @@ pg_start_backup(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } +/* Error cleanup callback for pg_start_backup */ +static void +pg_start_backup_callback(int code, Datum arg) +{ + /* Turn off forcePageWrites on failure */ + LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); + XLogCtl->Insert.forcePageWrites = false; + LWLockRelease(WALInsertLock); +} + /* * pg_stop_backup: finish taking an on-line backup dump * |