Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pW2gh-0007mJ-Tf for pgsql-hackers@arkaria.postgresql.org; Sat, 25 Feb 2023 22:06:40 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pW2gg-0002Gv-GU for pgsql-hackers@arkaria.postgresql.org; Sat, 25 Feb 2023 22:06:38 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pW2gg-0002Gj-3h for pgsql-hackers@lists.postgresql.org; Sat, 25 Feb 2023 22:06:38 +0000 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pW2gd-0003Ln-D2 for pgsql-hackers@lists.postgresql.org; Sat, 25 Feb 2023 22:06:37 +0000 Received: by mail-pf1-x42b.google.com with SMTP id y10so1476022pfi.8 for ; Sat, 25 Feb 2023 14:06:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=Mv5SqP1Bf/djTAVR03DXPubM8YFqfrGptvwyYkPP9fE=; b=ICFGpLIQ/44q5m7PaqfNPExvr14BhU/AL0dHs8BxtasYL4wsjahHEBE+uBpri6T9aN UL+G6UF5EGV+WrIMsykYKzwRK+UROGkzVGFjP/jnf7nC+nS8Pk8AJ/+h7gxepv3qoBB0 +ziqrWNSZw9xbR+UT29aFHy1O9nEpz5Wa3WCqRCCxWB6wID1MWqbhJeW4SstP5VQ4Byn SOjYzB4T0AIlLT6JuKU1/rI1ea0cldshUwu+fjFmUFrgHvBdEpcYrfDYIf7RbXkJlNWu LDH7Hugc99W50XEBeodqmIKJCRwFHCfnoV97nAuwtIRyaX8vXzVDVdgPtfLw8i6g0ksN f+mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Mv5SqP1Bf/djTAVR03DXPubM8YFqfrGptvwyYkPP9fE=; b=4FhTcfK30BHo1NyXT/olF3IZPsm74Jsb/2QBAYGwJSHSvdVJC+/CmvJNmSSwxBneTe EMz2KZiVPtSMm+SFxfNN00ew5Fqq83K3L0a+xBqN9LcjfdSdr+7RTqk9M+EeJ+kyT8G0 bAVviqZc5IZS/OmeA0P36D5SMBgWJ+W1eTI0bjASZ/WSnIiDHVHg85i4Wq2yL9eWtnkk KFcX+Pq3b+g3Fj13WbfpWO6F0De0dT95CkzBEjIOaaCcK8xqn2Jk/F9RTPtNbINU/CLf P/HAlXXu6BsYcHaDr94d1dTHgvTo8hbGczFpg41QLNkvVjOfTMM6VKtcCQlO7VUqtVqn bQRg== X-Gm-Message-State: AO0yUKXnZBfTtsQ5NOcdmLP5t8tA7utCcacYOmNynK0ZqQUTtwFrovDH bd3q/EylicQPnm5eU2dw/UM= X-Google-Smtp-Source: AK7set/auyxLMOjJbztUGVj73f9CTN3Y8MWc3Yj78ZuQtqTPWINeKpF4DlxL37sZz+1+YncZwJM5fw== X-Received: by 2002:a62:1ad1:0:b0:5a9:c772:85ab with SMTP id a200-20020a621ad1000000b005a9c77285abmr17116647pfa.22.1677362792812; Sat, 25 Feb 2023 14:06:32 -0800 (PST) Received: from nathanxps13 ([50.47.162.83]) by smtp.gmail.com with ESMTPSA id b1-20020a6567c1000000b00502ea3898a7sm1483320pgs.31.2023.02.25.14.06.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Feb 2023 14:06:32 -0800 (PST) Date: Sat, 25 Feb 2023 14:06:29 -0800 From: Nathan Bossart To: Andres Freund Cc: Thomas Munro , Michael Paquier , Robert Haas , Tom Lane , Fujii Masao , Postgres hackers Subject: Re: stopgap fix for signal handling during restore_command Message-ID: <20230225220629.GA1021641@nathanxps13> References: <20230223231503.GA743455@nathanxps13> <20230224043323.GA821522@nathanxps13> <20230225190742.lfopue3nkrvxxoie@awork3.anarazel.de> <20230225192825.GA868928@nathanxps13> <20230225195253.hzp6pyllhn4kw4g6@awork3.anarazel.de> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="IS0zKkzwUGydFO0o" Content-Disposition: inline In-Reply-To: <20230225195253.hzp6pyllhn4kw4g6@awork3.anarazel.de> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --IS0zKkzwUGydFO0o Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sat, Feb 25, 2023 at 11:52:53AM -0800, Andres Freund wrote: > I think I opined on this before, but we really ought to have a function to do > some minimal signal safe output. Implemented centrally, instead of being open > coded in a bunch of places. While looking around for the right place to put this, I noticed that there's a write_stderr() function in elog.c that we might be able to use. I used that in v9. WDYT? -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --IS0zKkzwUGydFO0o Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v9-0001-Move-extra-code-out-of-the-Pre-PostRestoreCommand.patch" From 7dcf8fe947ab7b6e0b37ddd42a08bbbc560d4a37 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 23 Feb 2023 14:27:48 -0800 Subject: [PATCH v9 1/2] Move extra code out of the Pre/PostRestoreCommand() block. If SIGTERM is received within this block, the startup process will immediately proc_exit() in the signal handler, so it is inadvisable to include any more code than is required in this section. This change moves the code recently added to this block (see 1b06d7b and 7fed801) to outside of the block. This ensures that only system() is called while proc_exit() might be called in the SIGTERM handler, which is how this code worked from v8.4 to v14. --- src/backend/access/transam/xlogarchive.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c index fcc87ff44f..41684418b6 100644 --- a/src/backend/access/transam/xlogarchive.c +++ b/src/backend/access/transam/xlogarchive.c @@ -159,20 +159,27 @@ RestoreArchivedFile(char *path, const char *xlogfname, (errmsg_internal("executing restore command \"%s\"", xlogRestoreCmd))); + fflush(NULL); + pgstat_report_wait_start(WAIT_EVENT_RESTORE_COMMAND); + /* - * Check signals before restore command and reset afterwards. + * PreRestoreCommand() informs the SIGTERM handler for the startup process + * that it should proc_exit() right away. This is done for the duration of + * the system() call because there isn't a good way to break out while it + * is executing. Since we might call proc_exit() in a signal handler, it + * is best to put any additional logic before or after the + * PreRestoreCommand()/PostRestoreCommand() section. */ PreRestoreCommand(); /* * Copy xlog from archival storage to XLOGDIR */ - fflush(NULL); - pgstat_report_wait_start(WAIT_EVENT_RESTORE_COMMAND); rc = system(xlogRestoreCmd); - pgstat_report_wait_end(); PostRestoreCommand(); + + pgstat_report_wait_end(); pfree(xlogRestoreCmd); if (rc == 0) -- 2.25.1 --IS0zKkzwUGydFO0o Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v9-0002-Don-t-proc_exit-in-startup-s-SIGTERM-handler-if-f.patch" From e41a13a77b1c6cf156387cee3ca49fb2f4b1253b Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Tue, 14 Feb 2023 09:44:53 -0800 Subject: [PATCH v9 2/2] Don't proc_exit() in startup's SIGTERM handler if forked by system(). Instead, emit a message to STDERR and _exit() in this case. This change also adds assertions to proc_exit(), ProcKill(), and AuxiliaryProcKill() to verify that these functions are not called by a process forked by system(), etc. --- src/backend/postmaster/startup.c | 17 ++++++++++++++++- src/backend/storage/ipc/ipc.c | 3 +++ src/backend/storage/lmgr/proc.c | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c index efc2580536..261f992357 100644 --- a/src/backend/postmaster/startup.c +++ b/src/backend/postmaster/startup.c @@ -19,6 +19,8 @@ */ #include "postgres.h" +#include + #include "access/xlog.h" #include "access/xlogrecovery.h" #include "access/xlogutils.h" @@ -121,7 +123,20 @@ StartupProcShutdownHandler(SIGNAL_ARGS) int save_errno = errno; if (in_restore_command) - proc_exit(1); + { + /* + * If we are in a child process (e.g., forked by system() in + * RestoreArchivedFile()), we don't want to call any exit callbacks. + * The parent will take care of that. + */ + if (MyProcPid == (int) getpid()) + proc_exit(1); + else + { + write_stderr("StartupProcShutdownHandler() called in child process\n"); + _exit(1); + } + } else shutdown_requested = true; WakeupRecovery(); diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c index 1904d21795..d5097dc008 100644 --- a/src/backend/storage/ipc/ipc.c +++ b/src/backend/storage/ipc/ipc.c @@ -103,6 +103,9 @@ static int on_proc_exit_index, void proc_exit(int code) { + /* proc_exit() is not safe in forked processes from system(), etc. */ + Assert(MyProcPid == (int) getpid()); + /* Clean up everything that must be cleaned up */ proc_exit_prepare(code); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 22b4278610..b9e2c3aafe 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -805,6 +805,7 @@ ProcKill(int code, Datum arg) dlist_head *procgloballist; Assert(MyProc != NULL); + Assert(MyProc->pid == (int) getpid()); /* not safe if forked by system(), etc. */ /* Make sure we're out of the sync rep lists */ SyncRepCleanupAtProcExit(); @@ -925,6 +926,7 @@ AuxiliaryProcKill(int code, Datum arg) PGPROC *proc; Assert(proctype >= 0 && proctype < NUM_AUXILIARY_PROCS); + Assert(MyProc->pid == (int) getpid()); /* not safe if forked by system(), etc. */ auxproc = &AuxiliaryProcs[proctype]; -- 2.25.1 --IS0zKkzwUGydFO0o--