At Wed, 11 Sep 2019 11:01:24 +0900 (Tokyo Standard Time), Kyotaro Horiguchi <horikyota....@gmail.com> wrote in <20190911.110124.96874741.horikyota....@gmail.com> > At Wed, 11 Sep 2019 01:36:15 +0000, "Tsunakawa, Takayuki" > <tsunakawa.ta...@jp.fujitsu.com> wrote in > <0A3221C70F24FB45833433255569204D1FD33579@G01JPEXMBYT05> > > From: Tom Lane [mailto:t...@sss.pgh.pa.us] > > > 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