postgresql/src/backend/storage/ipc/ipc.c
PostgreSQL Daemon 2ff501590b Tag appropriate files for rc3
Also performed an initial run through of upgrading our Copyright date to
extend to 2005 ... first run here was very simple ... change everything
where: grep 1996-2004 && the word 'Copyright' ... scanned through the
generated list with 'less' first, and after, to make sure that I only
picked up the right entries ...
2004-12-31 22:04:05 +00:00

198 lines
5.9 KiB
C

/*-------------------------------------------------------------------------
*
* ipc.c
* POSTGRES inter-process communication definitions.
*
* This file is misnamed, as it no longer has much of anything directly
* to do with IPC. The functionality here is concerned with managing
* exit-time cleanup for either a postmaster or a backend.
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipc.c,v 1.90 2004/12/31 22:00:56 pgsql Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include "miscadmin.h"
#include "storage/ipc.h"
/*
* This flag is set during proc_exit() to change ereport()'s behavior,
* so that an ereport() from an on_proc_exit routine cannot get us out
* of the exit procedure. We do NOT want to go back to the idle loop...
*/
bool proc_exit_inprogress = false;
/* ----------------------------------------------------------------
* exit() handling stuff
*
* These functions are in generally the same spirit as atexit(2),
* but provide some additional features we need --- in particular,
* we want to register callbacks to invoke when we are disconnecting
* from a broken shared-memory context but not exiting the postmaster.
*
* Callback functions can take zero, one, or two args: the first passed
* arg is the integer exitcode, the second is the Datum supplied when
* the callback was registered.
* ----------------------------------------------------------------
*/
#define MAX_ON_EXITS 20
static struct ONEXIT
{
void (*function) (int code, Datum arg);
Datum arg;
} on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
static int on_proc_exit_index,
on_shmem_exit_index;
/* ----------------------------------------------------------------
* proc_exit
*
* this function calls all the callbacks registered
* for it (to free resources) and then calls exit.
* This should be the only function to call exit().
* -cim 2/6/90
* ----------------------------------------------------------------
*/
void
proc_exit(int code)
{
/*
* Once we set this flag, we are committed to exit. Any ereport()
* will NOT send control back to the main loop, but right back here.
*/
proc_exit_inprogress = true;
/*
* Forget any pending cancel or die requests; we're doing our best to
* close up shop already. Note that the signal handlers will not set
* these flags again, now that proc_exit_inprogress is set.
*/
InterruptPending = false;
ProcDiePending = false;
QueryCancelPending = false;
/* And let's just make *sure* we're not interrupted ... */
ImmediateInterruptOK = false;
InterruptHoldoffCount = 1;
CritSectionCount = 0;
elog(DEBUG3, "proc_exit(%d)", code);
/* do our shared memory exits first */
shmem_exit(code);
/*
* call all the callbacks registered before calling exit().
*
* Note that since we decrement on_proc_exit_index each time, if a
* callback calls ereport(ERROR) or ereport(FATAL) then it won't be
* invoked again when control comes back here (nor will the
* previously-completed callbacks). So, an infinite loop should not
* be possible.
*/
while (--on_proc_exit_index >= 0)
(*on_proc_exit_list[on_proc_exit_index].function) (code,
on_proc_exit_list[on_proc_exit_index].arg);
elog(DEBUG3, "exit(%d)", code);
exit(code);
}
/* ------------------
* Run all of the on_shmem_exit routines --- but don't actually exit.
* This is used by the postmaster to re-initialize shared memory and
* semaphores after a backend dies horribly.
* ------------------
*/
void
shmem_exit(int code)
{
elog(DEBUG3, "shmem_exit(%d)", code);
/*
* call all the registered callbacks.
*
* As with proc_exit(), we remove each callback from the list before
* calling it, to avoid infinite loop in case of error.
*/
while (--on_shmem_exit_index >= 0)
(*on_shmem_exit_list[on_shmem_exit_index].function) (code,
on_shmem_exit_list[on_shmem_exit_index].arg);
on_shmem_exit_index = 0;
}
/* ----------------------------------------------------------------
* on_proc_exit
*
* this function adds a callback function to the list of
* functions invoked by proc_exit(). -cim 2/6/90
* ----------------------------------------------------------------
*/
void
on_proc_exit(void (*function) (int code, Datum arg), Datum arg)
{
if (on_proc_exit_index >= MAX_ON_EXITS)
ereport(FATAL,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg_internal("out of on_proc_exit slots")));
on_proc_exit_list[on_proc_exit_index].function = function;
on_proc_exit_list[on_proc_exit_index].arg = arg;
++on_proc_exit_index;
}
/* ----------------------------------------------------------------
* on_shmem_exit
*
* this function adds a callback function to the list of
* functions invoked by shmem_exit(). -cim 2/6/90
* ----------------------------------------------------------------
*/
void
on_shmem_exit(void (*function) (int code, Datum arg), Datum arg)
{
if (on_shmem_exit_index >= MAX_ON_EXITS)
ereport(FATAL,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg_internal("out of on_shmem_exit slots")));
on_shmem_exit_list[on_shmem_exit_index].function = function;
on_shmem_exit_list[on_shmem_exit_index].arg = arg;
++on_shmem_exit_index;
}
/* ----------------------------------------------------------------
* on_exit_reset
*
* this function clears all on_proc_exit() and on_shmem_exit()
* registered functions. This is used just after forking a backend,
* so that the backend doesn't believe it should call the postmaster's
* on-exit routines when it exits...
* ----------------------------------------------------------------
*/
void
on_exit_reset(void)
{
on_shmem_exit_index = 0;
on_proc_exit_index = 0;
}