1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-05 15:05:48 +02:00

Add forkSafe() to handle fork errors.

fork() rarely fails but we should definitely detect when it does so.
This commit is contained in:
David Steele 2019-04-02 13:50:02 +01:00
parent 1b48684713
commit 4c63279a19
7 changed files with 37 additions and 9 deletions

View File

@ -91,6 +91,10 @@
<p>Add locking capability to the remote command.</p>
</release-item>
<release-item>
<p>Add <code>forkSafe()</code> to handle fork errors.</p>
</release-item>
<release-item>
<p>Add <code>httpHeaderDup()</code>.</p>
</release-item>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -7,6 +7,7 @@ Fork Handler
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
int forkSafe(void);
void forkDetach(void);
#endif

View File

@ -38,6 +38,8 @@ There should not be any code outside the HARNESS_FORK_CHILD_BEGIN/END() and HARN
#include <sys/wait.h>
#include <unistd.h>
#include <common/fork.h>
/***********************************************************************************************************************************
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) \
{ \

View File

@ -12,7 +12,7 @@ testRun(void)
FUNCTION_HARNESS_VOID();
// *****************************************************************************************************************************
if (testBegin("forkAndDetach()"))
if (testBegin("forkSafe() and forkAndDetach()"))
{
int sessionId = getsid(0);