aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlogarchive.c20
-rw-r--r--src/backend/commands/copy.c3
-rw-r--r--src/backend/postmaster/pgarch.c10
-rw-r--r--src/common/wait_error.c43
-rw-r--r--src/include/port.h2
5 files changed, 55 insertions, 23 deletions
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index 90b150c7a8b..7825cfe532e 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -59,7 +59,6 @@ RestoreArchivedFile(char *path, const char *xlogfname,
char *endp;
const char *sp;
int rc;
- bool signaled;
struct stat stat_buf;
XLogSegNo restartSegNo;
XLogRecPtr restartRedoPtr;
@@ -288,17 +287,12 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* will perform an immediate shutdown when it sees us exiting
* unexpectedly.
*
- * Per the Single Unix Spec, shells report exit status > 128 when a called
- * command died on a signal. Also, 126 and 127 are used to report
- * problems such as an unfindable command; treat those as fatal errors
- * too.
+ * We treat hard shell errors such as "command not found" as fatal, too.
*/
- if (WIFSIGNALED(rc) && WTERMSIG(rc) == SIGTERM)
+ if (wait_result_is_signal(rc, SIGTERM))
proc_exit(1);
- signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
-
- ereport(signaled ? FATAL : DEBUG2,
+ ereport(wait_result_is_any_signal(rc, true) ? FATAL : DEBUG2,
(errmsg("could not restore file \"%s\" from archive: %s",
xlogfname, wait_result_to_str(rc))));
@@ -334,7 +328,6 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
char *endp;
const char *sp;
int rc;
- bool signaled;
XLogSegNo restartSegNo;
XLogRecPtr restartRedoPtr;
TimeLineID restartTli;
@@ -401,12 +394,9 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
{
/*
* If the failure was due to any sort of signal, it's best to punt and
- * abort recovery. See also detailed comments on signals in
- * RestoreArchivedFile().
+ * abort recovery. See comments in RestoreArchivedFile().
*/
- signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
-
- ereport((signaled && failOnSignal) ? FATAL : WARNING,
+ ereport((failOnSignal && wait_result_is_any_signal(rc, true)) ? FATAL : WARNING,
/*------
translator: First %s represents a recovery.conf parameter name like
"recovery_end_command", the 2nd is the value of that parameter, the
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 1a7d4f99ee8..226d2ef3dac 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -17,7 +17,6 @@
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -1713,7 +1712,7 @@ ClosePipeToProgram(CopyState cstate)
* problem.
*/
if (cstate->is_copy_from && !cstate->reached_eof &&
- WIFSIGNALED(pclose_rc) && WTERMSIG(pclose_rc) == SIGPIPE)
+ wait_result_is_signal(pclose_rc, SIGPIPE))
return;
ereport(ERROR,
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index ddf9d698e04..60e153ee2c9 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -573,13 +573,11 @@ pgarch_archiveXlog(char *xlog)
* If either the shell itself, or a called command, died on a signal,
* abort the archiver. We do this because system() ignores SIGINT and
* SIGQUIT while waiting; so a signal is very likely something that
- * should have interrupted us too. If we overreact it's no big deal,
- * the postmaster will just start the archiver again.
- *
- * Per the Single Unix Spec, shells report exit status > 128 when a
- * called command died on a signal.
+ * should have interrupted us too. Also die if the shell got a hard
+ * "command not found" type of error. If we overreact it's no big
+ * deal, the postmaster will just start the archiver again.
*/
- int lev = (WIFSIGNALED(rc) || WEXITSTATUS(rc) > 128) ? FATAL : LOG;
+ int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
if (WIFEXITED(rc))
{
diff --git a/src/common/wait_error.c b/src/common/wait_error.c
index f824a5f2af3..4fb5276961d 100644
--- a/src/common/wait_error.c
+++ b/src/common/wait_error.c
@@ -82,3 +82,46 @@ wait_result_to_str(int exitstatus)
return pstrdup(str);
}
+
+/*
+ * Return true if a wait(2) result indicates that the child process
+ * died due to the specified signal.
+ *
+ * The reason this is worth having a wrapper function for is that
+ * there are two cases: the signal might have been received by our
+ * immediate child process, or there might've been a shell process
+ * between us and the child that died. The shell will, per POSIX,
+ * report the child death using exit code 128 + signal number.
+ *
+ * If there is no possibility of an intermediate shell, this function
+ * need not (and probably should not) be used.
+ */
+bool
+wait_result_is_signal(int exit_status, int signum)
+{
+ if (WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum)
+ return true;
+ if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 128 + signum)
+ return true;
+ return false;
+}
+
+/*
+ * Return true if a wait(2) result indicates that the child process
+ * died due to any signal. We consider either direct child death
+ * or a shell report of child process death as matching the condition.
+ *
+ * If include_command_not_found is true, also return true for shell
+ * exit codes indicating "command not found" and the like
+ * (specifically, exit codes 126 and 127; see above).
+ */
+bool
+wait_result_is_any_signal(int exit_status, bool include_command_not_found)
+{
+ if (WIFSIGNALED(exit_status))
+ return true;
+ if (WIFEXITED(exit_status) &&
+ WEXITSTATUS(exit_status) > (include_command_not_found ? 125 : 128))
+ return true;
+ return false;
+}
diff --git a/src/include/port.h b/src/include/port.h
index b1ba645655f..0feddcdcaea 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -483,5 +483,7 @@ extern char *escape_single_quotes_ascii(const char *src);
/* port/wait_error.c */
extern char *wait_result_to_str(int exit_status);
+extern bool wait_result_is_signal(int exit_status, int signum);
+extern bool wait_result_is_any_signal(int exit_status, bool include_command_not_found);
#endif /* PG_PORT_H */