>From 412664b023638d9aa398ec26bcad98e182d9a959 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Thu, 8 Jan 2015 22:57:07 +0100 Subject: [PATCH 3/6] Add a default local latch for use in signal handlers. To do so move InitializeLatchSupport() into the new common process intialization functions and add two new global variables MyLocalLatch and MyLatch. MyLocalLatch always exists and points to a newly introduced local latch that exists in all processes. MyLatch initially points to MyLocalLatch but is redirected to the shared process latch in InitProcess/InitAuxiliaryProcess. When (Auxiliary)ProcKill detaches the process from it process entry it re-redirects it to the local latch again. This is primarily advantageous for two reasons: For one it simplifies dealing with the shared process latch, especially in signal handlers, because instead of having to check for MyProc, MyLatch can be used unconditionally. The bigger advantage is that a later patch that make FE/BE communication use latches now can just rely on the existance of a latch, even before doing InitProcess. --- src/backend/postmaster/autovacuum.c | 9 +++------ src/backend/postmaster/bgwriter.c | 6 ++---- src/backend/postmaster/checkpointer.c | 13 +++++-------- src/backend/postmaster/pgarch.c | 21 ++++++-------------- src/backend/postmaster/pgstat.c | 19 ++++++------------ src/backend/postmaster/syslogger.c | 18 +++++++---------- src/backend/postmaster/walwriter.c | 6 ++---- src/backend/storage/lmgr/proc.c | 33 ++++++++++++++------------------ src/backend/tcop/postgres.c | 12 ++++-------- src/backend/utils/init/globals.c | 2 ++ src/backend/utils/init/miscinit.c | 14 ++++++++++++++ src/backend/utils/misc/timeout.c | 6 ++---- src/include/miscadmin.h | 2 ++ src/include/storage/latch.h | 2 +- src/test/modules/test_shm_mq/worker.c | 3 +-- src/test/modules/worker_spi/worker_spi.c | 6 ++---- 16 files changed, 73 insertions(+), 99 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 2892e7b..f6c04ba 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1342,8 +1342,7 @@ avl_sighup_handler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -1355,8 +1354,7 @@ avl_sigusr2_handler(SIGNAL_ARGS) int save_errno = errno; got_SIGUSR2 = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -1368,8 +1366,7 @@ avl_sigterm_handler(SIGNAL_ARGS) int save_errno = errno; got_SIGTERM = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index e8ceef7..842af12 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -427,8 +427,7 @@ BgSigHupHandler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -440,8 +439,7 @@ ReqShutdownHandler(SIGNAL_ARGS) int save_errno = errno; shutdown_requested = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 3c9c216..237be12 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -360,7 +360,7 @@ CheckpointerMain(void) int rc; /* Clear any already-pending wakeups */ - ResetLatch(&MyProc->procLatch); + ResetLatch(MyLatch); /* * Process any requests or signals received recently. @@ -559,7 +559,7 @@ CheckpointerMain(void) cur_timeout = Min(cur_timeout, XLogArchiveTimeout - elapsed_secs); } - rc = WaitLatch(&MyProc->procLatch, + rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, cur_timeout * 1000L /* convert to ms */ ); @@ -832,8 +832,7 @@ ChkptSigHupHandler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -845,8 +844,7 @@ ReqCheckpointHandler(SIGNAL_ARGS) int save_errno = errno; checkpoint_requested = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -869,8 +867,7 @@ ReqShutdownHandler(SIGNAL_ARGS) int save_errno = errno; shutdown_requested = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 78dec3a..9b689af 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -78,11 +78,6 @@ static volatile sig_atomic_t got_SIGTERM = false; static volatile sig_atomic_t wakened = false; static volatile sig_atomic_t ready_to_stop = false; -/* - * Latch used by signal handlers to wake up the sleep in the main loop. - */ -static Latch mainloop_latch; - /* ---------- * Local function forward declarations * ---------- @@ -220,10 +215,6 @@ pgarch_forkexec(void) NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) { - InitializeLatchSupport(); /* needed for latch waits */ - - InitLatch(&mainloop_latch); /* initialize latch used in main loop */ - /* * Ignore all signals usually bound to some action in the postmaster, * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT. @@ -269,7 +260,7 @@ ArchSigHupHandler(SIGNAL_ARGS) /* set flag to re-read config file at next convenient time */ got_SIGHUP = true; - SetLatch(&mainloop_latch); + SetLatch(MyLatch); errno = save_errno; } @@ -287,7 +278,7 @@ ArchSigTermHandler(SIGNAL_ARGS) * archive commands. */ got_SIGTERM = true; - SetLatch(&mainloop_latch); + SetLatch(MyLatch); errno = save_errno; } @@ -300,7 +291,7 @@ pgarch_waken(SIGNAL_ARGS) /* set flag that there is work to be done */ wakened = true; - SetLatch(&mainloop_latch); + SetLatch(MyLatch); errno = save_errno; } @@ -313,7 +304,7 @@ pgarch_waken_stop(SIGNAL_ARGS) /* set flag to do a final cycle and shut down afterwards */ ready_to_stop = true; - SetLatch(&mainloop_latch); + SetLatch(MyLatch); errno = save_errno; } @@ -344,7 +335,7 @@ pgarch_MainLoop(void) */ do { - ResetLatch(&mainloop_latch); + ResetLatch(MyLatch); /* When we get SIGUSR2, we do one more archive cycle, then exit */ time_to_stop = ready_to_stop; @@ -397,7 +388,7 @@ pgarch_MainLoop(void) { int rc; - rc = WaitLatch(&mainloop_latch, + rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, timeout * 1000L); if (rc & WL_TIMEOUT) diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index fa87660..9b0c3c6 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -130,8 +130,6 @@ PgStat_MsgBgWriter BgWriterStats; */ NON_EXEC_STATIC pgsocket pgStatSock = PGINVALID_SOCKET; -static Latch pgStatLatch; - static struct sockaddr_storage pgStatAddr; static time_t last_pgstat_start_time; @@ -3151,15 +3149,10 @@ PgstatCollectorMain(int argc, char *argv[]) PgStat_Msg msg; int wr; - InitializeLatchSupport(); /* needed for latch waits */ - - /* Initialize private latch for use by signal handlers */ - InitLatch(&pgStatLatch); - /* * Ignore all signals usually bound to some action in the postmaster, * except SIGHUP and SIGQUIT. Note we don't need a SIGUSR1 handler to - * support latch operations, because pgStatLatch is local not shared. + * support latch operations, because we only use a local latch. */ pqsignal(SIGHUP, pgstat_sighup_handler); pqsignal(SIGINT, SIG_IGN); @@ -3205,7 +3198,7 @@ PgstatCollectorMain(int argc, char *argv[]) for (;;) { /* Clear any already-pending wakeups */ - ResetLatch(&pgStatLatch); + ResetLatch(MyLocalLatch); /* * Quit if we get SIGQUIT from the postmaster. @@ -3363,7 +3356,7 @@ PgstatCollectorMain(int argc, char *argv[]) /* Sleep until there's something to do */ #ifndef WIN32 - wr = WaitLatchOrSocket(&pgStatLatch, + wr = WaitLatchOrSocket(MyLocalLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE, pgStatSock, -1L); @@ -3379,7 +3372,7 @@ PgstatCollectorMain(int argc, char *argv[]) * to not provoke "pgstat wait timeout" complaints from * backend_read_statsfile. */ - wr = WaitLatchOrSocket(&pgStatLatch, + wr = WaitLatchOrSocket(MyLocalLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT, pgStatSock, 2 * 1000L /* msec */ ); @@ -3409,7 +3402,7 @@ pgstat_exit(SIGNAL_ARGS) int save_errno = errno; need_exit = true; - SetLatch(&pgStatLatch); + SetLatch(MyLocalLatch); errno = save_errno; } @@ -3421,7 +3414,7 @@ pgstat_sighup_handler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - SetLatch(&pgStatLatch); + SetLatch(MyLocalLatch); errno = save_errno; } diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index 6e6754e..41b8dbb 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -85,7 +85,6 @@ static FILE *csvlogFile = NULL; NON_EXEC_STATIC pg_time_t first_syslogger_file_time = 0; static char *last_file_name = NULL; static char *last_csv_file_name = NULL; -static Latch sysLoggerLatch; /* * Buffers for saving partial messages from different backends. @@ -231,9 +230,6 @@ SysLoggerMain(int argc, char *argv[]) syslogPipe[1] = 0; #endif - /* Initialize private latch for use by signal handlers */ - InitLatch(&sysLoggerLatch); - /* * Properly accept or ignore signals the postmaster might send us * @@ -299,7 +295,7 @@ SysLoggerMain(int argc, char *argv[]) #endif /* Clear any already-pending wakeups */ - ResetLatch(&sysLoggerLatch); + ResetLatch(MyLatch); /* * Process any requests or signals received recently. @@ -425,7 +421,7 @@ SysLoggerMain(int argc, char *argv[]) * Sleep until there's something to do */ #ifndef WIN32 - rc = WaitLatchOrSocket(&sysLoggerLatch, + rc = WaitLatchOrSocket(MyLatch, WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags, syslogPipe[0], cur_timeout); @@ -477,7 +473,7 @@ SysLoggerMain(int argc, char *argv[]) */ LeaveCriticalSection(&sysloggerSection); - (void) WaitLatch(&sysLoggerLatch, + (void) WaitLatch(MyLatch, WL_LATCH_SET | cur_flags, cur_timeout); @@ -1058,7 +1054,7 @@ pipeThread(void *arg) { if (ftell(syslogFile) >= Log_RotationSize * 1024L || (csvlogFile != NULL && ftell(csvlogFile) >= Log_RotationSize * 1024L)) - SetLatch(&sysLoggerLatch); + SetLatch(MyLatch); } LeaveCriticalSection(&sysloggerSection); } @@ -1070,7 +1066,7 @@ pipeThread(void *arg) flush_pipe_input(logbuffer, &bytes_in_logbuffer); /* set the latch to waken the main thread, which will quit */ - SetLatch(&sysLoggerLatch); + SetLatch(MyLatch); LeaveCriticalSection(&sysloggerSection); _endthread(); @@ -1350,7 +1346,7 @@ sigHupHandler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - SetLatch(&sysLoggerLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -1362,7 +1358,7 @@ sigUsr1Handler(SIGNAL_ARGS) int save_errno = errno; rotation_requested = true; - SetLatch(&sysLoggerLatch); + SetLatch(MyLatch); errno = save_errno; } diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 8ff5005..297faf5 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -347,8 +347,7 @@ WalSigHupHandler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -360,8 +359,7 @@ WalShutdownHandler(SIGNAL_ARGS) int save_errno = errno; shutdown_requested = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 777c60b..3ef1d5e 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -291,13 +291,6 @@ InitProcess(void) elog(ERROR, "you already exist"); /* - * Initialize process-local latch support. This could fail if the kernel - * is low on resources, and if so we want to exit cleanly before acquiring - * any shared-memory resources. - */ - InitializeLatchSupport(); - - /* * Try to get a proc struct from the free list. If this fails, we must be * out of PGPROC structures (not to mention semaphores). * @@ -391,10 +384,15 @@ InitProcess(void) SHMQueueElemInit(&(MyProc->syncRepLinks)); /* - * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch. - * Note that there's no particular need to do ResetLatch here. + * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch + * on it. That allows us to repoint the process latch, which so far + * points to process local one, to the shared one. Set the new latch, so a + * potentially pending even from the old latch is definitely visible on + * the new one. */ OwnLatch(&MyProc->procLatch); + MyLatch = &MyProc->procLatch; + SetLatch(MyLatch); /* * We might be reusing a semaphore that belonged to a failed process. So @@ -475,13 +473,6 @@ InitAuxiliaryProcess(void) elog(ERROR, "you already exist"); /* - * Initialize process-local latch support. This could fail if the kernel - * is low on resources, and if so we want to exit cleanly before acquiring - * any shared-memory resources. - */ - InitializeLatchSupport(); - - /* * We use the ProcStructLock to protect assignment and releasing of * AuxiliaryProcs entries. * @@ -551,6 +542,8 @@ InitAuxiliaryProcess(void) * Note that there's no particular need to do ResetLatch here. */ OwnLatch(&MyProc->procLatch); + MyLatch = &MyProc->procLatch; + SetLatch(MyLatch); /* * We might be reusing a semaphore that belonged to a failed process. So @@ -800,10 +793,11 @@ ProcKill(int code, Datum arg) ReplicationSlotRelease(); /* - * Clear MyProc first; then disown the process latch. This is so that - * signal handlers won't try to clear the process latch after it's no - * longer ours. + * Reset MyLatch to the process local one. This is so that signal + * handlers won't try to access the shard process latch after it's no + * longer ours. After that clear MyProc and disown the shared latch. */ + MyLatch = MyLocalLatch; proc = MyProc; MyProc = NULL; DisownLatch(&proc->procLatch); @@ -871,6 +865,7 @@ AuxiliaryProcKill(int code, Datum arg) * signal handlers won't try to clear the process latch after it's no * longer ours. */ + MyLatch = MyLocalLatch; proc = MyProc; MyProc = NULL; DisownLatch(&proc->procLatch); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 5e6d0f7..8bf006b 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -2608,8 +2608,7 @@ die(SIGNAL_ARGS) } /* If we're still here, waken anything waiting on the process latch */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -2650,8 +2649,7 @@ StatementCancelHandler(SIGNAL_ARGS) } /* If we're still here, waken anything waiting on the process latch */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -2676,8 +2674,7 @@ SigHupHandler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -2815,8 +2812,7 @@ RecoveryConflictInterrupt(ProcSignalReason reason) * waiting on that latch, expecting to get interrupted by query cancels et * al., would also need to set set_latch_on_sigusr1. */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index dc5c8d6..685ad7f 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -37,6 +37,8 @@ volatile uint32 CritSectionCount = 0; int MyProcPid; pg_time_t MyStartTime; struct Port *MyProcPort; +struct Latch *MyLocalLatch; +struct Latch *MyLatch; long MyCancelKey; int MyPMChildSlot; diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index aea26dd..707348d 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -38,6 +38,7 @@ #include "postmaster/postmaster.h" #include "storage/fd.h" #include "storage/ipc.h" +#include "storage/latch.h" #include "storage/pg_shmem.h" #include "storage/proc.h" #include "storage/procarray.h" @@ -54,6 +55,7 @@ ProcessingMode Mode = InitProcessing; /* List of lock files to be removed at proc exit */ static List *lock_files = NIL; +static Latch LocalLatchData; /* ---------------------------------------------------------------- * ignoring system indexes support stuff @@ -188,6 +190,12 @@ InitPostmasterChild(void) /* We don't want the postmaster's proc_exit() handlers */ on_exit_reset(); + /* Initialize process-local latch support */ + InitializeLatchSupport(); + MyLocalLatch = &LocalLatchData; + MyLatch = &LocalLatchData; + InitLatch(MyLocalLatch); + /* * If possible, make this process a group leader, so that the postmaster * can signal any child processes too. Not all processes will have @@ -214,6 +222,12 @@ InitStandaloneProcess(const char *argv0) MyStartTime = time(NULL); /* set our start time in case we call elog */ + /* Initialize process-local latch support */ + InitializeLatchSupport(); + MyLocalLatch = &LocalLatchData; + MyLatch = &LocalLatchData; + InitLatch(MyLocalLatch); + /* Compute paths, no postmaster to inherit from */ if (my_exec_path[0] == '\0') { diff --git a/src/backend/utils/misc/timeout.c b/src/backend/utils/misc/timeout.c index 1dec492..ce4bc13 100644 --- a/src/backend/utils/misc/timeout.c +++ b/src/backend/utils/misc/timeout.c @@ -284,11 +284,9 @@ handle_sig_alarm(SIGNAL_ARGS) /* * SIGALRM is always cause for waking anything waiting on the process - * latch. Cope with MyProc not being there, as the startup process also - * uses this signal handler. + * latch. */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); /* * Fire any pending timeouts, but only if we're enabled to do so. diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index b94a944..81a5057 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -148,6 +148,8 @@ extern int max_worker_processes; extern PGDLLIMPORT int MyProcPid; extern PGDLLIMPORT pg_time_t MyStartTime; extern PGDLLIMPORT struct Port *MyProcPort; +extern PGDLLIMPORT struct Latch *MyLatch; +extern PGDLLIMPORT struct Latch *MyLocalLatch; extern long MyCancelKey; extern int MyPMChildSlot; diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h index 138a748..0d9b14b 100644 --- a/src/include/storage/latch.h +++ b/src/include/storage/latch.h @@ -92,7 +92,7 @@ * the public functions. It is defined here to allow embedding Latches as * part of bigger structs. */ -typedef struct +typedef struct Latch { sig_atomic_t is_set; bool is_shared; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index dec058b..a9d9e0e 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -211,8 +211,7 @@ handle_sigterm(SIGNAL_ARGS) { int save_errno = errno; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); if (!proc_exit_inprogress) { diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index ac0f59c..10080ed 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -74,8 +74,7 @@ worker_spi_sigterm(SIGNAL_ARGS) int save_errno = errno; got_sigterm = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -91,8 +90,7 @@ worker_spi_sighup(SIGNAL_ARGS) int save_errno = errno; got_sighup = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } -- 2.2.1.212.gc5b9256