diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index b57669336..59419a707 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -91,6 +91,10 @@
Add locking capability to the remote command.
+
+ Add forkSafe()
to handle fork errors.
+
+
Add httpHeaderDup()
.
diff --git a/src/command/archive/get/get.c b/src/command/archive/get/get.c
index 753f1ac3f..2f3f40a50 100644
--- a/src/command/archive/get/get.c
+++ b/src/command/archive/get/get.c
@@ -227,12 +227,11 @@ cmdArchiveGet(void)
for (unsigned int queueIdx = 0; queueIdx < strLstSize(queue); queueIdx++)
strLstAdd(commandExec, strLstGet(queue, queueIdx));
- // Release the lock and mark the async process as forked
+ // Release the lock so the child process can acquire it
lockRelease(true);
- forked = true;
// Fork off the async process
- if (fork() == 0)
+ if (forkSafe() == 0)
{
// Detach from parent process
forkDetach();
@@ -242,6 +241,10 @@ cmdArchiveGet(void)
execvp(strPtr(cfgExe()), (char ** const)strLstPtr(commandExec)) == -1,
ExecuteError, "unable to execute '%s'", cfgCommandName(cfgCmdArchiveGetAsync));
}
+
+ // Mark the async process as forked so it doesn't get forked again. A single run of the async process should be
+ // enough to do the job, running it again won't help anything.
+ forked = true;
}
// Exit loop if WAL was found
diff --git a/src/command/archive/push/push.c b/src/command/archive/push/push.c
index e07ae962d..63f34decc 100644
--- a/src/command/archive/push/push.c
+++ b/src/command/archive/push/push.c
@@ -301,12 +301,11 @@ cmdArchivePush(void)
strLstInsert(commandExec, 0, cfgExe());
strLstAdd(commandExec, strPath(walFile));
- // Release the lock and mark the async process as forked
+ // Release the lock so the child process can acquire it
lockRelease(true);
- forked = true;
// Fork off the async process
- if (fork() == 0)
+ if (forkSafe() == 0)
{
// Detach from parent process
forkDetach();
@@ -316,6 +315,10 @@ cmdArchivePush(void)
execvp(strPtr(cfgExe()), (char ** const)strLstPtr(commandExec)) == -1,
ExecuteError, "unable to execute '%s'", cfgCommandName(cfgCmdArchiveGetAsync));
}
+
+ // Mark the async process as forked so it doesn't get forked again. A single run of the async process should be
+ // enough to do the job, running it again won't help anything.
+ forked = true;
}
// Now that the async process has been launched, confess any errors that are found
diff --git a/src/common/fork.c b/src/common/fork.c
index eed95bd91..1769c6ac6 100644
--- a/src/common/fork.c
+++ b/src/common/fork.c
@@ -8,7 +8,22 @@ Fork Handler
#include "common/log.h"
/***********************************************************************************************************************************
-Fork a new process and detach it so it can continue running after the parent process has exited. This is not a typical daemon
+Fork a new process and throw an error if it fails
+***********************************************************************************************************************************/
+int
+forkSafe(void)
+{
+ FUNCTION_LOG_VOID(logLevelTrace);
+
+ int result = fork();
+
+ THROW_ON_SYS_ERROR(result == -1, PathMissingError, "unable to fork");
+
+ FUNCTION_LOG_RETURN(INT, result);
+}
+
+/***********************************************************************************************************************************
+Detach a forked process and detach it so it can continue running after the parent process has exited. This is not a typical daemon
startup because the parent process may continue to run and perform work for some time.
***********************************************************************************************************************************/
void
diff --git a/src/common/fork.h b/src/common/fork.h
index 8be1e754c..ec7086af2 100644
--- a/src/common/fork.h
+++ b/src/common/fork.h
@@ -7,6 +7,7 @@ Fork Handler
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
+int forkSafe(void);
void forkDetach(void);
#endif
diff --git a/test/src/common/harnessFork.h b/test/src/common/harnessFork.h
index 3f1ec5ad8..c131da662 100644
--- a/test/src/common/harnessFork.h
+++ b/test/src/common/harnessFork.h
@@ -38,6 +38,8 @@ There should not be any code outside the HARNESS_FORK_CHILD_BEGIN/END() and HARN
#include
#include
+#include
+
/***********************************************************************************************************************************
Define the max number of child processes allowed
***********************************************************************************************************************************/
@@ -133,7 +135,7 @@ Create a child process
"unable to create write pipe for child process %u", HARNESS_FORK_PROCESS_TOTAL()); \
} \
\
- HARNESS_FORK_PROCESS_ID(HARNESS_FORK_PROCESS_TOTAL()) = fork(); \
+ HARNESS_FORK_PROCESS_ID(HARNESS_FORK_PROCESS_TOTAL()) = forkSafe(); \
\
if (HARNESS_FORK_PROCESS_ID(HARNESS_FORK_PROCESS_TOTAL()) == 0) \
{ \
diff --git a/test/src/module/common/forkTest.c b/test/src/module/common/forkTest.c
index ab24f1bc9..5b61b4343 100644
--- a/test/src/module/common/forkTest.c
+++ b/test/src/module/common/forkTest.c
@@ -12,7 +12,7 @@ testRun(void)
FUNCTION_HARNESS_VOID();
// *****************************************************************************************************************************
- if (testBegin("forkAndDetach()"))
+ if (testBegin("forkSafe() and forkAndDetach()"))
{
int sessionId = getsid(0);