@ -27,6 +27,7 @@
# ifdef PROFILE_PID_DIR
# include "postmaster/autovacuum.h"
# endif
# include "storage/dsm.h"
# include "storage/ipc.h"
# include "tcop/tcopprot.h"
@ -64,14 +65,19 @@ static void proc_exit_prepare(int code);
# define MAX_ON_EXITS 20
static st ruct ONEXIT
struct ONEXIT
{
pg_on_exit_callback function ;
Datum arg ;
} on_proc_exit_list [ MAX_ON_EXITS ] , on_shmem_exit_list [ MAX_ON_EXITS ] ;
} ;
static struct ONEXIT on_proc_exit_list [ MAX_ON_EXITS ] ;
static struct ONEXIT on_shmem_exit_list [ MAX_ON_EXITS ] ;
static struct ONEXIT before_shmem_exit_list [ MAX_ON_EXITS ] ;
static int on_proc_exit_index ,
on_shmem_exit_index ;
on_shmem_exit_index ,
before_shmem_exit_index ;
/* ----------------------------------------------------------------
@ -202,25 +208,60 @@ proc_exit_prepare(int 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 .
* semaphores after a backend dies horribly . As with proc_exit ( ) , we
* remove each callback from the list before calling it , to avoid
* infinite loop in case of error .
* - - - - - - - - - - - - - - - - - -
*/
void
shmem_exit ( int code )
{
elog ( DEBUG3 , " shmem_exit(%d): %d callbacks to make " ,
code , on_shmem_exit_index ) ;
/*
* Call before_shmem_exit callbacks .
*
* These should be things that need most of the system to still be
* up and working , such as cleanup of temp relations , which requires
* catalog access ; or things that need to be completed because later
* cleanup steps depend on them , such as releasing lwlocks .
*/
elog ( DEBUG3 , " shmem_exit(%d): %d before_shmem_exit callbacks to make " ,
code , before_shmem_exit_index ) ;
while ( - - before_shmem_exit_index > = 0 )
( * before_shmem_exit_list [ before_shmem_exit_index ] . function ) ( code ,
before_shmem_exit_list [ before_shmem_exit_index ] . arg ) ;
before_shmem_exit_index = 0 ;
/*
* call all the registered callbacks .
* Call dynamic shared memory callbacks .
*
* These serve the same purpose as late callbacks , but for dynamic shared
* memory segments rather than the main shared memory segment .
* dsm_backend_shutdown ( ) has the same kind of progressive logic we use
* for the main shared memory segment ; namely , it unregisters each
* callback before invoking it , so that we don ' t get stuck in an infinite
* loop if one of those callbacks itself throws an ERROR or FATAL .
*
* Note that explicitly calling this function here is quite different
* from registering it as an on_shmem_exit callback for precisely this
* reason : if one dynamic shared memory callback errors out , the remaining
* callbacks will still be invoked . Thus , hard - coding this call puts it
* equal footing with callbacks for the main shared memory segment .
*/
dsm_backend_shutdown ( ) ;
/*
* Call on_shmem_exit callbacks .
*
* As with proc_exit ( ) , we remove each callback from the list before
* calling it , to avoid infinite loop in case of error .
* These are generally releasing low - level shared memory resources . In
* some cases , this is a backstop against the possibility that the early
* callbacks might themselves fail , leading to re - entry to this routine ;
* in other cases , it ' s cleanup that only happens at process exit .
*/
elog ( DEBUG3 , " shmem_exit(%d): %d on_shmem_exit callbacks to make " ,
code , on_shmem_exit_index ) ;
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 ;
}
@ -269,11 +310,40 @@ on_proc_exit(pg_on_exit_callback function, Datum arg)
}
}
/* ----------------------------------------------------------------
* before_shmem_exit
*
* Register early callback to perform user - level cleanup ,
* e . g . transaction abort , before we begin shutting down
* low - level subsystems .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void
before_shmem_exit ( pg_on_exit_callback function , Datum arg )
{
if ( before_shmem_exit_index > = MAX_ON_EXITS )
ereport ( FATAL ,
( errcode ( ERRCODE_PROGRAM_LIMIT_EXCEEDED ) ,
errmsg_internal ( " out of before_shmem_exit slots " ) ) ) ;
before_shmem_exit_list [ before_shmem_exit_index ] . function = function ;
before_shmem_exit_list [ before_shmem_exit_index ] . arg = arg ;
+ + before_shmem_exit_index ;
if ( ! atexit_callback_setup )
{
atexit ( atexit_callback ) ;
atexit_callback_setup = true ;
}
}
/* ----------------------------------------------------------------
* on_shmem_exit
*
* this function adds a callback function to the list of
* functions invoked by shmem_exit ( ) . - cim 2 / 6 / 90
* Register ordinary callback to perform low - level shutdown
* ( e . g . releasing our PGPROC ) ; run after before_shmem_exit
* callbacks and before on_proc_exit callbacks .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void
@ -297,21 +367,22 @@ on_shmem_exit(pg_on_exit_callback function, Datum arg)
}
/* ----------------------------------------------------------------
* cancel_shmem_exit
* cancel_before_ shmem_exit
*
* this function removes an entry , if present , from the list of
* functions to be invoked by shmem_exit ( ) . For simplicity ,
* only the latest entry can be removed . ( We could work harder
* but there is no need for current uses . )
* this function removes a previously - registed before_shmem_exit
* callback . For simplicity , only the latest entry can be
* removed . ( We could work harder but there is no need fo r
* current uses . )
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void
cancel_shmem_exit ( pg_on_exit_callback function , Datum arg )
cancel_before_ shmem_exit ( pg_on_exit_callback function , Datum arg )
{
if ( on_shmem_exit_index > 0 & &
on_shmem_exit_list [ on_shmem_exit_index - 1 ] . function = = function & &
on_shmem_exit_list [ on_shmem_exit_index - 1 ] . arg = = arg )
- - on_shmem_exit_index ;
if ( before_shmem_exit_index > 0 & &
before_shmem_exit_list [ before_shmem_exit_index - 1 ] . function
= = function & &
before_shmem_exit_list [ before_shmem_exit_index - 1 ] . arg = = arg )
- - before_shmem_exit_index ;
}
/* ----------------------------------------------------------------
@ -326,6 +397,7 @@ cancel_shmem_exit(pg_on_exit_callback function, Datum arg)
void
on_exit_reset ( void )
{
before_shmem_exit_index = 0 ;
on_shmem_exit_index = 0 ;
on_proc_exit_index = 0 ;
}