1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-07 00:35:37 +02:00

Move async forking and more error handling to C.

The Perl process was exiting directly when called but that interfered with proper locking for the forked async process. Now Perl returns results to the C process which handles all errors, including signals.
This commit is contained in:
David Steele
2018-04-12 20:42:26 -04:00
parent 6fd0c3dcaa
commit f0250dab4b
49 changed files with 1058 additions and 884 deletions

View File

@ -20,7 +20,7 @@ Debug Asserts
Begin the command
***********************************************************************************************************************************/
void
cmdBegin()
cmdBegin(bool logOption)
{
ASSERT_DEBUG_COMMAND_SET();
@ -30,77 +30,82 @@ cmdBegin()
MEM_CONTEXT_TEMP_BEGIN()
{
// Basic info on command start
String *info = strNewFmt("%s command begin %s:", cfgCommandName(cfgCommand()), PGBACKREST_VERSION);
String *info = strNewFmt("%s command begin", cfgCommandName(cfgCommand()));
// Loop though options and add the ones that are interesting
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
if (logOption)
{
// Skip the option if it is not valid
if (!cfgOptionValid(optionId))
continue;
strCatFmt(info, " %s:", PGBACKREST_VERSION);
// If option was negated
if (cfgOptionNegate(optionId))
strCatFmt(info, " --no-%s", cfgOptionName(optionId));
// If option was reset
else if (cfgOptionReset(optionId))
strCatFmt(info, " --reset-%s", cfgOptionName(optionId));
// Else set and not default
else if (cfgOptionSource(optionId) != cfgSourceDefault && cfgOptionTest(optionId))
// Loop though options and add the ones that are interesting
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
{
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Skip the option if it is not valid
if (!cfgOptionValid(optionId))
continue;
// Don't show redacted options
if (cfgDefOptionSecure(optionDefId))
strCatFmt(info, " --%s=<redacted>", cfgOptionName(optionId));
// Output boolean option
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
strCatFmt(info, " --%s", cfgOptionName(optionId));
// Output other options
else
// If option was negated
if (cfgOptionNegate(optionId))
strCatFmt(info, " --no-%s", cfgOptionName(optionId));
// If option was reset
else if (cfgOptionReset(optionId))
strCatFmt(info, " --reset-%s", cfgOptionName(optionId));
// Else set and not default
else if (cfgOptionSource(optionId) != cfgSourceDefault && cfgOptionTest(optionId))
{
StringList *valueList = NULL;
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Generate the values of hash options
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeHash)
{
valueList = strLstNew();
const KeyValue *optionKv = cfgOptionKv(optionId);
const VariantList *keyList = kvKeyList(optionKv);
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
{
strLstAdd(
valueList,
strNewFmt(
"%s=%s", strPtr(varStr(varLstGet(keyList, keyIdx))),
strPtr(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx))))));
}
}
// Generate values for list options
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeList)
{
valueList = strLstNewVarLst(cfgOptionLst(optionId));
}
// Else only one value
// Don't show redacted options
if (cfgDefOptionSecure(optionDefId))
strCatFmt(info, " --%s=<redacted>", cfgOptionName(optionId));
// Output boolean option
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
strCatFmt(info, " --%s", cfgOptionName(optionId));
// Output other options
else
{
valueList = strLstNew();
strLstAdd(valueList, varStrForce(cfgOption(optionId)));
}
StringList *valueList = NULL;
// Output options and values
for (unsigned int valueListIdx = 0; valueListIdx < strLstSize(valueList); valueListIdx++)
{
const String *value = strLstGet(valueList, valueListIdx);
// Generate the values of hash options
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeHash)
{
valueList = strLstNew();
strCatFmt(info, " --%s", cfgOptionName(optionId));
const KeyValue *optionKv = cfgOptionKv(optionId);
const VariantList *keyList = kvKeyList(optionKv);
if (strchr(strPtr(value), ' ') != NULL)
value = strNewFmt("\"%s\"", strPtr(value));
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
{
strLstAdd(
valueList,
strNewFmt(
"%s=%s", strPtr(varStr(varLstGet(keyList, keyIdx))),
strPtr(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx))))));
}
}
// Generate values for list options
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeList)
{
valueList = strLstNewVarLst(cfgOptionLst(optionId));
}
// Else only one value
else
{
valueList = strLstNew();
strLstAdd(valueList, varStrForce(cfgOption(optionId)));
}
strCatFmt(info, "=%s", strPtr(value));
// Output options and values
for (unsigned int valueListIdx = 0; valueListIdx < strLstSize(valueList); valueListIdx++)
{
const String *value = strLstGet(valueList, valueListIdx);
strCatFmt(info, " --%s", cfgOptionName(optionId));
if (strchr(strPtr(value), ' ') != NULL)
value = strNewFmt("\"%s\"", strPtr(value));
strCatFmt(info, "=%s", strPtr(value));
}
}
}
}
@ -116,9 +121,10 @@ cmdBegin()
End the command
***********************************************************************************************************************************/
void
cmdEnd(int code)
cmdEnd(int code, const String *errorMessage)
{
ASSERT_DEBUG_COMMAND_SET();
ASSERT_DEBUG(code == 0 || errorMessage != NULL);
// Skip this log message if it won't be output. It's not too expensive but since we skipped cmdBegin(), may as well.
if (logWill(cfgLogLevelDefault()))
@ -131,7 +137,7 @@ cmdEnd(int code)
if (code == 0)
strCat(info, "completed successfully");
else
strCatFmt(info, "aborted with exception [%03d]", code);
strCat(info, strPtr(errorMessage));
LOG_ANY(cfgLogLevelDefault(), 0, strPtr(info));
}