Skip to content

Commit 4d271e3

Browse files
committed
checkpointer: Request checkpoint via latch instead of signal
The motivation for this change is that a future commit will use SIGINT for another purpose (postmaster requesting WAL access to be shut down) and that there no other signals that we could readily use (see code comment for the reason why SIGTERM shouldn't be used). But it's also a tad nicer / more efficient to use SetLatch(), as it avoids sending signals when checkpointer already is busy. Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com> Discussion: https://postgr.es/m/kgng5nrvnlv335evmsuvpnh354rw7qyazl73kdysev2cr2v5zu@m3cfzxicm5kp
1 parent a5579a9 commit 4d271e3

File tree

1 file changed

+18
-40
lines changed

1 file changed

+18
-40
lines changed

src/backend/postmaster/checkpointer.c

+18-40
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,6 @@ static bool ImmediateCheckpointRequested(void);
159159
static bool CompactCheckpointerRequestQueue(void);
160160
static void UpdateSharedMemoryConfig(void);
161161

162-
/* Signal handlers */
163-
static void ReqCheckpointHandler(SIGNAL_ARGS);
164-
165162

166163
/*
167164
* Main entry point for checkpointer process
@@ -191,7 +188,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len)
191188
* tell us it's okay to shut down (via SIGUSR2).
192189
*/
193190
pqsignal(SIGHUP, SignalHandlerForConfigReload);
194-
pqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */
191+
pqsignal(SIGINT, SIG_IGN);
195192
pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */
196193
/* SIGQUIT handler was already set up by InitPostmasterChild */
197194
pqsignal(SIGALRM, SIG_IGN);
@@ -860,23 +857,6 @@ IsCheckpointOnSchedule(double progress)
860857
}
861858

862859

863-
/* --------------------------------
864-
* signal handler routines
865-
* --------------------------------
866-
*/
867-
868-
/* SIGINT: set flag to run a normal checkpoint right away */
869-
static void
870-
ReqCheckpointHandler(SIGNAL_ARGS)
871-
{
872-
/*
873-
* The signaling process should have set ckpt_flags nonzero, so all we
874-
* need do is ensure that our main loop gets kicked out of any wait.
875-
*/
876-
SetLatch(MyLatch);
877-
}
878-
879-
880860
/* --------------------------------
881861
* communication with backends
882862
* --------------------------------
@@ -990,38 +970,36 @@ RequestCheckpoint(int flags)
990970
SpinLockRelease(&CheckpointerShmem->ckpt_lck);
991971

992972
/*
993-
* Send signal to request checkpoint. It's possible that the checkpointer
994-
* hasn't started yet, or is in process of restarting, so we will retry a
995-
* few times if needed. (Actually, more than a few times, since on slow
996-
* or overloaded buildfarm machines, it's been observed that the
997-
* checkpointer can take several seconds to start.) However, if not told
998-
* to wait for the checkpoint to occur, we consider failure to send the
999-
* signal to be nonfatal and merely LOG it. The checkpointer should see
1000-
* the request when it does start, with or without getting a signal.
973+
* Set checkpointer's latch to request checkpoint. It's possible that the
974+
* checkpointer hasn't started yet, so we will retry a few times if
975+
* needed. (Actually, more than a few times, since on slow or overloaded
976+
* buildfarm machines, it's been observed that the checkpointer can take
977+
* several seconds to start.) However, if not told to wait for the
978+
* checkpoint to occur, we consider failure to set the latch to be
979+
* nonfatal and merely LOG it. The checkpointer should see the request
980+
* when it does start, with or without the SetLatch().
1001981
*/
1002982
#define MAX_SIGNAL_TRIES 600 /* max wait 60.0 sec */
1003983
for (ntries = 0;; ntries++)
1004984
{
1005-
if (CheckpointerShmem->checkpointer_pid == 0)
985+
volatile PROC_HDR *procglobal = ProcGlobal;
986+
ProcNumber checkpointerProc = procglobal->checkpointerProc;
987+
988+
if (checkpointerProc == INVALID_PROC_NUMBER)
1006989
{
1007990
if (ntries >= MAX_SIGNAL_TRIES || !(flags & CHECKPOINT_WAIT))
1008991
{
1009992
elog((flags & CHECKPOINT_WAIT) ? ERROR : LOG,
1010-
"could not signal for checkpoint: checkpointer is not running");
993+
"could not notify checkpoint: checkpointer is not running");
1011994
break;
1012995
}
1013996
}
1014-
else if (kill(CheckpointerShmem->checkpointer_pid, SIGINT) != 0)
997+
else
1015998
{
1016-
if (ntries >= MAX_SIGNAL_TRIES || !(flags & CHECKPOINT_WAIT))
1017-
{
1018-
elog((flags & CHECKPOINT_WAIT) ? ERROR : LOG,
1019-
"could not signal for checkpoint: %m");
1020-
break;
1021-
}
999+
SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch);
1000+
/* notified successfully */
1001+
break;
10221002
}
1023-
else
1024-
break; /* signal sent successfully */
10251003

10261004
CHECK_FOR_INTERRUPTS();
10271005
pg_usleep(100000L); /* wait 0.1 sec, then retry */

0 commit comments

Comments
 (0)