At Wed, 11 Sep 2019 11:01:24 +0900 (Tokyo Standard Time), Kyotaro Horiguchi
<[email protected]> wrote in
<[email protected]>
> At Wed, 11 Sep 2019 01:36:15 +0000, "Tsunakawa, Takayuki"
> <[email protected]> wrote in
> <0A3221C70F24FB45833433255569204D1FD33579@G01JPEXMBYT05>
> > From: Tom Lane [mailto:[email protected]]
> > > SIGTERM, which needs to be adjusted. For another, its
> > > SIGQUIT handler does exit(1) not _exit(2), which seems rather
> > > dubious ... should we make it more like the rest? I think
> > > the reasoning there might've been that if some DBA decides to
> > > SIGQUIT the archiver, we don't need to force a database-wide
> > > reset; but why exactly should we tolerate that?
> >
> > postmaster doesn't distinguish return codes other than 0 for the archiver,
> > and just starts the archiver unless postmaster is shutting down. So we can
> > use _exit(2) like the other children.
> >
> > Can't we use SIGKILL instead of SIGINT/SIGTERM to stop the grandchildren,
> > just in case they are slow to respond to or ignore SIGINT/SIGTERM? That
> > matches the idea of pg_ctl's immediate shutdown.
>
> Perhaps +1.. immediate -> SIGKILL fast -> SIGTERM?
We send SIGUSR2 to archive while fast shutdown. It would be
enough for pg_system to do signal(SNGINT, DIG_DFL) andsignal
signal(SIGQUIT, SIG_IGN) then remember the child's pid somewhere.
Then each process send SIGKILL to the remembered process in
sigquit handler. (I'm not sure what happens if kill(0,
SIGKILL)).
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index f84f882c4c..1fe7b5dd0a 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -108,6 +108,50 @@ static bool pgarch_archiveXlog(char *xlog);
static bool pgarch_readyXlog(char *xlog);
static void pgarch_archiveDone(char *xlog);
+pid_t system_pid = -1;
+
+static void
+pg_system_kill()
+{
+ if (system_pid >= 0)
+ kill(system_pid, SIGKILL);
+}
+
+static int
+pg_system(char *cmd)
+{
+ int status;
+ long result;
+
+
+ system_pid = fork();
+ if (system_pid == 0)
+ {
+ char *new_argv[4] = {"sh", "-c", cmd, NULL};
+
+ pqsignal(SIGINT, SIG_DFL);
+ pqsignal(SIGQUIT, SIG_IGN);
+ (void) execve ("/bin/sh", (char * const *) new_argv, __environ);
+ _exit(127);
+ }
+
+ if (system_pid < 0)
+ return -1;
+
+ do
+ {
+ result = waitpid(system_pid, &status, 0);
+ } while (result == -1L && errno == EINTR);
+
+ if (result != system_pid)
+ {
+ system_pid = -1;
+ return -1;
+ }
+
+ system_pid = -1;
+ return status;
+}
/* ------------------------------------------------------------
* Public functions called from postmaster follow
@@ -255,6 +299,9 @@ PgArchiverMain(int argc, char *argv[])
static void
pgarch_exit(SIGNAL_ARGS)
{
+ if (postgres_signal_arg == SIGQUIT)
+ pg_system_kill();
+
/* SIGQUIT means curl up and die ... */
exit(1);
}
@@ -620,7 +667,7 @@ pgarch_archiveXlog(char *xlog)
snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
set_ps_display(activitymsg, false);
- rc = system(xlogarchcmd);
+ rc = pg_system(xlogarchcmd);
if (rc != 0)
{
/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a5446d54bb..d9b85a5228 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3964,6 +3964,8 @@ PostmasterStateMachine(void)
static void
signal_child(pid_t pid, int signal)
{
+ if (pid == PgArchPID)
+ elog(LOG, "Send %d to archiver", signal);
if (kill(pid, signal) < 0)
elog(DEBUG3, "kill(%ld,%d) failed: %m", (long) pid, signal);
#ifdef HAVE_SETSID