From 29c8b97ae41d6d285ab01e84b9848a74636bd81a Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Fri, 24 Feb 2023 13:08:31 +1300 Subject: [PATCH] XXX inject SIGTERM into system() at an inconvenient moment --- src/backend/access/transam/xlogarchive.c | 68 +++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c index 41684418b6..87e16f8a21 100644 --- a/src/backend/access/transam/xlogarchive.c +++ b/src/backend/access/transam/xlogarchive.c @@ -33,6 +33,72 @@ #include "storage/ipc.h" #include "storage/lwlock.h" +/* + * Copied from OpenBSD's lib/libc/stdlib/system.c because it's short and sweet + * and doesn't require any weird headers. The use of vfork() also screws the + * timing down a little (glibc's impl would use fork(), so child and parent + * would race to run proc_exec, while this version runs the handler in the + * child, and then the parent). + */ + +#define _PATH_BSHELL "/bin/sh" + +static int +doomed_system(const char *command) +{ + pid_t pid, cpid; + struct sigaction intsave, quitsave, sa; + sigset_t mask, omask; + int pstat; + char *argp[] = {"sh", "-c", NULL, NULL}; + + if (!command) /* just checking... */ + return(1); + + argp[2] = (char *)command; + + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGQUIT); + sigprocmask(SIG_BLOCK, &mask, &omask); + switch (cpid = fork()) { + case -1: /* error */ + sigprocmask(SIG_SETMASK, &omask, NULL); + return(-1); + case 0: /* child */ + sigprocmask(SIG_SETMASK, &omask, NULL); + + kill(-getppid(), SIGTERM); // XXX a badly timed SIGTERM to group + + execve(_PATH_BSHELL, argp, environ); + _exit(127); + } + + sleep(2); + + /* Ignore SIGINT and SIGQUIT while waiting for command to complete. */ + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + sigaction(SIGINT, &sa, &intsave); + sigaction(SIGQUIT, &sa, &quitsave); + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGQUIT); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + + do { + pid = waitpid(cpid, &pstat, 0); + } while (pid == -1 && errno == EINTR); + + sigprocmask(SIG_SETMASK, &omask, NULL); + sigaction(SIGINT, &intsave, NULL); + sigaction(SIGQUIT, &quitsave, NULL); + + return (pid == -1 ? -1 : pstat); +} + /* * Attempt to retrieve the specified file from off-line archival storage. * If successful, fill "path" with its complete path (note that this will be @@ -175,7 +241,7 @@ RestoreArchivedFile(char *path, const char *xlogfname, /* * Copy xlog from archival storage to XLOGDIR */ - rc = system(xlogRestoreCmd); + rc = doomed_system(xlogRestoreCmd); PostRestoreCommand(); -- 2.39.1