1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Improve libbacktrace implementation.

The libbacktrace feature has not been working since the move to meson because libbacktrace detection was not added to the meson build. Add libbacktrace to meson and improve the feature so that it can be compiled into release builds.

The prior implementation fetched line numbers with each stack trace push. Not only was this slow but it missed any functions that were not being tracked on our stack.

Instead just examine the backtrace when an error happens and merge it with the info we have on our stack. If the backtrace is not available then the output remains as before.

Also remove --backtrace from test.pl since the library is now auto-detected.

Leave this library out of the production build for now to give it a little time to shake out in testing.
This commit is contained in:
David Steele 2023-01-11 11:19:26 +07:00
parent 0dd2997714
commit c826429123
16 changed files with 348 additions and 115 deletions

View File

@ -9,6 +9,26 @@ _end
_fini
_init
_start
backtrace_alloc
backtrace_close
backtrace_create_state
backtrace_dwarf_add
backtrace_free
backtrace_full
backtrace_get_view
backtrace_initialize
backtrace_open
backtrace_pcinfo
backtrace_qsort
backtrace_release_view
backtrace_syminfo
backtrace_syminfo_to_full_callback
backtrace_syminfo_to_full_error_callback
backtrace_uncompress_lzma
backtrace_uncompress_zdebug
backtrace_vector_finish
backtrace_vector_grow
backtrace_vector_release
data_start
environ@GLIBC_2.2.5
main

View File

@ -133,6 +133,13 @@ add_project_arguments(cc.get_supported_arguments('-fmacro-prefix-map=@0@/test/sr
####################################################################################################################################
configuration = configuration_data()
# Find optional backtrace library
lib_backtrace = cc.find_library('backtrace', required: false)
if lib_backtrace.found()
configuration.set('HAVE_LIBBACKTRACE', true, description: 'Is libbacktrace present?')
endif
# Find required bz2 library
lib_bz2 = cc.find_library('bz2')

View File

@ -7,7 +7,7 @@ Stack Trace Handler
#include <stdio.h>
#include <string.h>
#ifdef WITH_BACKTRACE
#ifdef HAVE_LIBBACKTRACE
#include <backtrace.h>
#include <backtrace-supported.h>
#endif
@ -45,46 +45,11 @@ static struct StackTraceLocal
int stackSize; // Stack size
StackTraceData stack[STACK_TRACE_MAX]; // Stack data
char functionParamBuffer[32 * 1024]; // Buffer to hold function parameters
} stackTraceLocal;
/**********************************************************************************************************************************/
#ifdef WITH_BACKTRACE
static struct StackTraceBackLocal
{
#ifdef HAVE_LIBBACKTRACE
struct backtrace_state *backTraceState; // Backtrace state struct
} stackTraceBackLocal;
FN_EXTERN void
stackTraceInit(const char *exe)
{
if (stackTraceBackLocal.backTraceState == NULL)
stackTraceBackLocal.backTraceState = backtrace_create_state(exe, false, NULL, NULL);
}
static int
backTraceCallback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
{
(void)(data);
(void)(pc);
(void)(filename);
(void)(function);
if (stackTraceLocal.stackSize > 0)
stackTraceLocal.stack[stackTraceLocal.stackSize - 1].fileLine = (unsigned int)lineno;
return 1;
}
static void
backTraceCallbackError(void *data, const char *msg, int errnum)
{
(void)data;
(void)msg;
(void)errnum;
}
#endif
} stackTraceLocal;
/**********************************************************************************************************************************/
#ifdef DEBUG
@ -128,11 +93,6 @@ stackTracePush(const char *fileName, const char *functionName, LogLevel function
{
ASSERT(stackTraceLocal.stackSize < STACK_TRACE_MAX - 1);
// Get line number from backtrace if available
#ifdef WITH_BACKTRACE
backtrace_full(stackTraceBackLocal.backTraceState, 2, backTraceCallback, backTraceCallbackError, NULL);
#endif
// Set function info
StackTraceData *data = &stackTraceLocal.stack[stackTraceLocal.stackSize];
@ -303,16 +263,118 @@ stackTraceFmt(char *buffer, size_t bufferSize, size_t bufferUsed, const char *fo
return (size_t)result;
}
/***********************************************************************************************************************************
Helper to trim off extra path before the src path
***********************************************************************************************************************************/
static const char *
stackTraceTrimSrc(const char *const fileName)
{
const char *const src = strstr(fileName, "src/");
return src == NULL ? fileName : src + 4;
}
/**********************************************************************************************************************************/
#ifdef HAVE_LIBBACKTRACE
typedef struct StackTraceBackData
{
bool firstCall;
bool firstLine;
int stackIdx;
size_t result;
char *const buffer;
const size_t bufferSize;
} StackTraceBackData;
// Callback to add backtrace data when available
static int
stackTraceBackCallback(
void *const dataVoid, const uintptr_t pc, const char *fileName, const int fileLine, const char *const functionName)
{
(void)(pc);
StackTraceBackData *const data = dataVoid;
// Stop if the stack has been exhausted
if (data->stackIdx < 0)
return true;
// Catch any unset parameters which indicates the debug data is not available
if (fileName == NULL || fileLine == 0 || functionName == NULL)
{
// If this is the first call then stop because the top of the backtrace must be one of our functions
if (data->firstCall)
return true;
// Else return but do not stop
data->firstCall = false;
return false;
}
// Reset first call
data->firstCall = false;
// If the function name matches combine backtrace data with stack data
const StackTraceData *const traceData = &stackTraceLocal.stack[data->stackIdx];
if (strcmp(functionName, traceData->functionName) == 0)
{
data->result += stackTraceFmt(
data->buffer, data->bufferSize, data->result, "%s%s:%s:%d:(%s)", data->firstLine ? "" : "\n",
stackTraceTrimSrc(traceData->fileName), functionName, fileLine, stackTraceParamIdx(data->stackIdx));
data->stackIdx--;
}
// Else just use stack data. Skip any functions in the error module since they are not useful for the user
else
{
fileName = stackTraceTrimSrc(fileName);
if (strcmp(fileName, "common/error.c") == 0)
return false;
data->result += stackTraceFmt(
data->buffer, data->bufferSize, data->result, "%s%s:%s:%d:(no parameters available)", data->firstLine ? "" : "\n",
fileName, functionName, fileLine);
}
// Reset first line
data->firstLine = false;
// Stop when the main function has been processed
return strcmp(functionName, "main") == 0;
}
// Dummy error callback. If there is an error just generate the default stack trace.
static void
stackTraceBackErrorCallback(void *data, const char *msg, int errnum)
{
(void)data;
(void)msg;
(void)errnum;
}
#endif
// Helper to build stack trace when backtrace is not available
#ifdef HAVE_LIBBACKTRACE
static size_t
stackTraceToZDefault(
#else
FN_EXTERN size_t
stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char *functionName, unsigned int fileLine)
stackTraceToZ(
#endif // HAVE_LIBBACKTRACE
char *const buffer, const size_t bufferSize, const char *fileName, const char *const functionName,
const unsigned int fileLine)
{
size_t result = 0;
const char *param = "test build required for parameters";
int stackIdx = stackTraceLocal.stackSize - 1;
// If the current function passed in is the same as the top function on the stack then use the parameters for that function
if (stackTraceLocal.stackSize > 0 && strcmp(fileName, stackTraceLocal.stack[stackIdx].fileName) == 0 &&
fileName = stackTraceTrimSrc(fileName);
if (stackTraceLocal.stackSize > 0 && strcmp(fileName, stackTraceTrimSrc(stackTraceLocal.stack[stackIdx].fileName)) == 0 &&
strcmp(functionName, stackTraceLocal.stack[stackIdx].functionName) == 0)
{
param = stackTraceParamIdx(stackTraceLocal.stackSize - 1);
@ -332,9 +394,9 @@ stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char
// Output the rest of the stack
for (; stackIdx >= 0; stackIdx--)
{
StackTraceData *data = &stackTraceLocal.stack[stackIdx];
const StackTraceData *const data = &stackTraceLocal.stack[stackIdx];
result += stackTraceFmt(buffer, bufferSize, result, "\n%s:%s", data->fileName, data->functionName);
result += stackTraceFmt(buffer, bufferSize, result, "\n%s:%s", stackTraceTrimSrc(data->fileName), data->functionName);
if (data->fileLine > 0)
result += stackTraceFmt(buffer, bufferSize, result, ":%u", data->fileLine);
@ -346,6 +408,38 @@ stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char
return result;
}
#ifdef HAVE_LIBBACKTRACE
FN_EXTERN size_t
stackTraceToZ(
char *const buffer, const size_t bufferSize, const char *const fileName, const char *const functionName,
const unsigned int fileLine)
{
// Attempt to use backtrace data
StackTraceBackData data =
{
.firstCall = true,
.firstLine = true,
.stackIdx = stackTraceLocal.stackSize - 1,
.result = 0,
.buffer = buffer,
.bufferSize = bufferSize,
};
if (stackTraceLocal.backTraceState == NULL)
stackTraceLocal.backTraceState = backtrace_create_state(NULL, false, NULL, NULL);
backtrace_full(stackTraceLocal.backTraceState, 2, stackTraceBackCallback, stackTraceBackErrorCallback, &data);
// If the backtrace was not available generate default stack trace
if (data.result == 0)
return stackTraceToZDefault(buffer, bufferSize, fileName, functionName, fileLine);
return data.result;
}
#endif // HAVE_LIBBACKTRACE
/**********************************************************************************************************************************/
FN_EXTERN void
stackTraceClean(const unsigned int tryDepth, const bool fatal)

View File

@ -31,11 +31,6 @@ Macros to access internal functions
/***********************************************************************************************************************************
Internal Functions
***********************************************************************************************************************************/
// Backtrace init
#ifdef WITH_BACKTRACE
void stackTraceInit(const char *exe);
#endif
#ifdef DEBUG
// Enable/disable test function logging
FN_EXTERN void stackTraceTestStart(void);

View File

@ -73,10 +73,6 @@ main(int argListSize, const char *argList[])
storageHelperInit(storageHelperList);
#ifdef WITH_BACKTRACE
stackTraceInit(argList[0]);
#endif
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(INT, argListSize);
FUNCTION_LOG_PARAM(CHARPY, argList);

View File

@ -93,6 +93,7 @@ build_code = executable(
src_common,
src_build_code,
dependencies: [
lib_backtrace,
lib_bz2,
lib_xml,
lib_yaml
@ -253,6 +254,7 @@ executable(
help_auto_c_inc,
interface_auto_c_inc,
dependencies : [
lib_backtrace,
lib_bz2,
lib_openssl,
lib_lz4,

View File

@ -69,7 +69,6 @@ sub new
$self->{bCoverageUnit},
$self->{bCoverageSummary},
$self->{bOptimize},
$self->{bBackTrace},
$self->{bProfile},
$self->{iScale},
$self->{strTimeZone},
@ -102,7 +101,6 @@ sub new
{name => 'bCoverageUnit'},
{name => 'bCoverageSummary'},
{name => 'bOptimize'},
{name => 'bBackTrace'},
{name => 'bProfile'},
{name => 'iScale'},
{name => 'strTimeZone', required => false},

View File

@ -44,8 +44,6 @@ use constant VMDEF_PGSQL_BIN => 'psql-bin
push @EXPORT, qw(VMDEF_PGSQL_BIN);
use constant VMDEF_LCOV_VERSION => 'lcov-version';
push @EXPORT, qw(VMDEF_LCOV_VERSION);
use constant VMDEF_WITH_BACKTRACE => 'with-backtrace';
push @EXPORT, qw(VMDEF_WITH_BACKTRACE);
use constant VMDEF_WITH_LZ4 => 'with-lz4';
push @EXPORT, qw(VMDEF_WITH_LZ4);
use constant VMDEF_WITH_ZST => 'with-zst';
@ -191,7 +189,6 @@ my $oyVm =
&VM_ARCH => VM_ARCH_I386,
&VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin',
&VMDEF_WITH_BACKTRACE => true,
&VMDEF_WITH_ZST => true,
&VM_DB =>
@ -218,7 +215,6 @@ my $oyVm =
&VMDEF_COVERAGE_C => true,
&VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin',
&VMDEF_WITH_BACKTRACE => true,
&VMDEF_WITH_ZST => true,
&VM_DB =>
@ -252,7 +248,6 @@ my $oyVm =
&VMDEF_COVERAGE_C => true,
&VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin',
&VMDEF_WITH_BACKTRACE => true,
&VMDEF_WITH_ZST => true,
&VM_DB =>
@ -433,18 +428,6 @@ sub hostArch
push @EXPORT, qw(hostArch);
####################################################################################################################################
# Does the VM support libbacktrace?
####################################################################################################################################
sub vmWithBackTrace
{
my $strVm = shift;
return ($oyVm->{$strVm}{&VMDEF_WITH_BACKTRACE} ? true : false);
}
push @EXPORT, qw(vmWithBackTrace);
####################################################################################################################################
# Does the VM support liblz4?
####################################################################################################################################

View File

@ -533,6 +533,7 @@ testBldUnit(TestBuild *const this)
" '%s/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_backtrace,\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"

View File

@ -7,13 +7,6 @@ C Debug Harness
#ifdef HRN_FEATURE_DEBUG
#include "common/debug.h"
#ifdef WITH_BACKTRACE
#define FUNCTION_HARNESS_INIT(exe) \
stackTraceInit(exe)
#else
#define FUNCTION_HARNESS_INIT(exe)
#endif
// Set line numer of the current function in the stack trace. This is used to give more detailed info about which test macro
// caused an error.
#ifdef DEBUG
@ -61,7 +54,6 @@ C Debug Harness
#define FUNCTION_HARNESS_RETURN_VOID() \
STACK_TRACE_POP(false);
#else
#define FUNCTION_HARNESS_INIT(exe)
#define FUNCTION_HARNESS_STACK_TRACE_LINE_SET(lineNo)
#define FUNCTION_HARNESS_BEGIN()
#define FUNCTION_HARNESS_PARAM(typeMacroPrefix, param)

View File

@ -64,6 +64,7 @@ executable(
arg_unity,
],
dependencies: [
lib_backtrace,
lib_bz2,
lib_yaml,
],

View File

@ -253,7 +253,7 @@ testRun(void)
assert(
strcmp(
errorStackTrace(),
TEST_PGB_PATH "/test/src/module/common/errorTest.c:testTryRecurse:29:(test build required for parameters)")
"module/common/errorTest.c:testTryRecurse:29:(test build required for parameters)")
== 0);
assert(strcmp(errorMessage(), "too many nested try blocks") == 0);
assert(strcmp(errorName(), AssertError.name) == 0);

View File

@ -3,6 +3,43 @@ Test Stack Trace Handler
***********************************************************************************************************************************/
#include <assert.h>
#ifdef HAVE_LIBBACKTRACE
FN_NO_RETURN void
testStackTraceError3(void)
{
stackTracePush("module/common/stackTraceTest.c", "testStackTraceError3", logLevelTrace);
THROW(FormatError, "test error");
}
FN_NO_RETURN void
testStackTraceError2(void)
{
testStackTraceError3();
}
FN_NO_RETURN void
testStackTraceError1(void)
{
stackTracePush("src/file1.c", "testStackTraceError1", logLevelDebug);
testStackTraceError2();
}
FN_NO_RETURN void
testStackTraceError5(void)
{
THROW_FMT(FormatError, "test error fmt");
}
FN_NO_RETURN void
testStackTraceError4(void)
{
stackTracePush("file4.c", "testStackTraceError4", logLevelTrace);
testStackTraceError5();
}
#endif
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
@ -25,19 +62,107 @@ testRun(void)
}
// *****************************************************************************************************************************
if (testBegin("stackTraceInit() and stackTraceError()"))
if (testBegin("libBackTrace"))
{
#ifdef WITH_BACKTRACE
stackTraceInit(BOGUS_STR);
#ifdef HAVE_LIBBACKTRACE
// *************************************************************************************************************************
TEST_TITLE("empty error function");
// This time does nothing
stackTraceInit(BOGUS_STR);
TEST_RESULT_VOID(stackTraceBackErrorCallback(NULL, NULL, 0), "call error");
// This will call the error routine since we passed a bogus exe
assert(stackTracePush("file1.c", "function1", logLevelDebug) == logLevelDebug);
stackTracePop("file1.c", "function1", false);
// *************************************************************************************************************************
TEST_TITLE("missing backtrace data");
stackTraceLocal.backTraceState = NULL;
StackTraceBackData data =
{
.firstCall = true,
};
TEST_RESULT_INT(stackTraceBackCallback(&data, 0, NULL, 0, NULL), true, "all null, first call");
data.firstCall = false;
TEST_RESULT_INT(stackTraceBackCallback(&data, 0, "fileName", 0, NULL), false, "two null");
TEST_RESULT_INT(stackTraceBackCallback(&data, 0, "fileName", 2, NULL), false, "one null");
// Note that it is possible for libbacktrace to be present but not have any debug symbols to work with so handle that by
// looking for an alternative error. However this will not work when coverage is required.
// *************************************************************************************************************************
TEST_TITLE("backtrace data");
TRY_BEGIN()
{
testStackTraceError1();
}
CATCH_ANY()
{
TRY_BEGIN()
{
TEST_RESULT_Z(
errorStackTrace(),
"module/common/stackTraceTest.c:testStackTraceError3:12:(trace log level required for parameters)\n"
"module/common/stackTraceTest.c:testStackTraceError2:18:(no parameters available)\n"
"file1.c:testStackTraceError1:25:(debug log level required for parameters)",
"check stack trace");
}
CATCH(TestError)
{
hrnTestResultEnd();
TRY_BEGIN()
{
testStackTraceError1();
}
CATCH_ANY()
{
TEST_RESULT_Z(
errorStackTrace(),
"module/common/stackTraceTest.c:testStackTraceError3:12:(trace log level required for parameters)\n"
"file1.c:testStackTraceError1:(debug log level required for parameters)",
"check stack trace");
}
TRY_END();
}
TRY_END();
}
TRY_END();
TRY_BEGIN()
{
testStackTraceError4();
}
CATCH_ANY()
{
TRY_BEGIN()
{
TEST_RESULT_Z(
errorStackTrace(),
"module/common/stackTraceTest.c:testStackTraceError5:31:(no parameters available)\n"
"file4.c:testStackTraceError4:38:(trace log level required for parameters)",
"check stack trace");
}
CATCH(TestError)
{
hrnTestResultEnd();
TRY_BEGIN()
{
testStackTraceError4();
}
CATCH_ANY()
{
TEST_RESULT_Z(
errorStackTrace(),
"module/common/stackTraceTest.c:testStackTraceError5:31:(test build required for parameters)\n"
" ... function(s) omitted ...\n"
"file4.c:testStackTraceError4:(trace log level required for parameters)",
"check stack trace");
}
TRY_END();
}
TRY_END();
}
TRY_END();
#endif
}
@ -65,9 +190,6 @@ testRun(void)
{
char buffer[4096];
#ifdef WITH_BACKTRACE
stackTraceInit(testExe());
#endif
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("check size of StackTraceData");
@ -94,7 +216,12 @@ testRun(void)
stackTraceParamLog();
assert(strcmp(stackTraceParam(), "void") == 0);
stackTraceToZ(buffer, sizeof(buffer), "file1.c", "function2", 99);
#ifdef HAVE_LIBBACKTRACE
stackTraceToZDefault(
#else
stackTraceToZ(
#endif
buffer, sizeof(buffer), "file1.c", "function2", 99);
TEST_RESULT_Z(
buffer,
@ -135,7 +262,7 @@ testRun(void)
// Munge the previous previous param in the stack so that the next one will just barely fit
stackTraceLocal.stack[stackTraceLocal.stackSize - 1].paramSize = bufferOverflow - 1;
assert(stackTracePush("file4.c", "function4", logLevelDebug) == logLevelTrace);
assert(stackTracePush("src/file4.c", "function4", logLevelDebug) == logLevelTrace);
stackTraceLocal.stack[stackTraceLocal.stackSize - 2].fileLine = 7777;
stackTraceParamLog();
assert(stackTraceLocal.stackSize == 5);
@ -150,7 +277,12 @@ testRun(void)
stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param1"), STACK_TRACE_PARAM_MAX, "value1"));
assert(strcmp(stackTraceParam(), "buffer full - parameters not available") == 0);
stackTraceToZ(buffer, sizeof(buffer), "file4.c", "function4", 99);
#ifdef HAVE_LIBBACKTRACE
stackTraceToZDefault(
#else
stackTraceToZ(
#endif
buffer, sizeof(buffer), "../pgbackrest/src/file4.c", "function4", 99);
TEST_RESULT_Z(
buffer,
@ -161,7 +293,25 @@ testRun(void)
"file1.c:function1:7777:(void)",
"stack trace");
stackTracePop("file4.c", "function4", false);
#ifdef HAVE_LIBBACKTRACE
stackTraceToZDefault(
#else
stackTraceToZ(
#endif
buffer, sizeof(buffer), "file5.c", "function4", 99);
TEST_RESULT_Z(
buffer,
"file5.c:function4:99:(test build required for parameters)\n"
" ... function(s) omitted ...\n"
"file4.c:function4:(buffer full - parameters not available)\n"
"file3.c:function3:7777:(param1: value1, param2: value2)\n"
"file2.c:function2:7777:(param1: value1)\n"
"file1.c:function2:7777:(debug log level required for parameters)\n"
"file1.c:function1:7777:(void)",
"stack trace");
stackTracePop("src/file4.c", "function4", false);
assert(stackTraceLocal.stackSize == 4);
// Check that stackTracePop() works with test tracing

View File

@ -295,6 +295,7 @@ testRun(void)
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_backtrace,\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
@ -399,6 +400,7 @@ testRun(void)
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_backtrace,\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
@ -605,6 +607,7 @@ testRun(void)
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_backtrace,\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
@ -764,6 +767,7 @@ testRun(void)
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_backtrace,\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"

View File

@ -151,9 +151,6 @@ main(int argListSize, const char *argList[])
exit(25);
}
// Initialize stack trace for the harness
FUNCTION_HARNESS_INIT(argList[0]);
FUNCTION_HARNESS_BEGIN();
FUNCTION_HARNESS_PARAM(INT, argListSize);
FUNCTION_HARNESS_PARAM(CHARPY, argList);

View File

@ -84,7 +84,6 @@ test.pl [options]
--no-coverage don't run coverage on C unit tests (saves time)
--no-coverage-report run coverage but don't generate coverage report (saves time)
--no-optimize don't do compile optimization for C (saves compile time)
--backtrace enable backtrace when available (adds stack trace line numbers -- very slow)
--profile generate profile info
--no-debug don't generate a debug build
--scale scale performance tests
@ -158,7 +157,6 @@ my $bGenOnly = false;
my $bGenCheck = false;
my $bMinGen = false;
my $bCodeCount = false;
my $bBackTrace = false;
my $bProfile = false;
my $bNoValgrind = false;
my $bNoOptimize = false;
@ -208,7 +206,6 @@ GetOptions ('q|quiet' => \$bQuiet,
'gen-check' => \$bGenCheck,
'min-gen' => \$bMinGen,
'code-count' => \$bCodeCount,
'backtrace' => \$bBackTrace,
'profile' => \$bProfile,
'no-valgrind' => \$bNoValgrind,
'no-optimize' => \$bNoOptimize,
@ -729,12 +726,9 @@ eval
$rhBinBuild->{$strBuildVM} = false;
# Build configure/compile options and see if they have changed from the previous build
my $strCFlags =
(vmWithBackTrace($strBuildVM) && $bBackTrace ? ' -DWITH_BACKTRACE' : '') .
($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : '');
my $strLdFlags = vmWithBackTrace($strBuildVM) && $bBackTrace ? '-lbacktrace' : '';
my $strCFlags = ($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : '');
my $strConfigOptions = (vmDebugIntegration($strBuildVM) ? ' --enable-test' : '');
my $strBuildFlags = "CFLAGS_EXTRA=${strCFlags}\nLDFLAGS_EXTRA=${strLdFlags}\nCONFIGURE=${strConfigOptions}";
my $strBuildFlags = "CFLAGS_EXTRA=${strCFlags}\nCONFIGURE=${strConfigOptions}";
my $strBuildFlagFile = "${strBinPath}/${strBuildVM}/build.flags";
my $bBuildOptionsDiffer = buildPutDiffers($oStorageBackRest, $strBuildFlagFile, $strBuildFlags);
@ -760,8 +754,7 @@ eval
executeTest(
'docker exec -i -u ' . TEST_USER . ' test-build ' .
"${strMakeCmd} -s -j ${iBuildMax}" . ($bLogDetail ? '' : ' --silent') .
" --directory ${strBuildPath} CFLAGS_EXTRA='${strCFlags}'" .
($strLdFlags ne '' ? " LDFLAGS_EXTRA='${strLdFlags}'" : ''),
" --directory ${strBuildPath} CFLAGS_EXTRA='${strCFlags}'",
{bShowOutputAsync => $bLogDetail});
}
}
@ -1062,7 +1055,7 @@ eval
$oStorageTest, $strBackRestBase, $strTestPath, $$oyTestRun[$iTestIdx], $bDryRun, $bVmOut, $iVmIdx, $iVmMax,
$strMakeCmd, $iTestIdx, $iTestMax, $strLogLevel, $strLogLevelTest, $strLogLevelTestFile, !$bNoLogTimestamp,
$bShowOutputAsync, $bNoCleanup, $iRetry, !$bNoValgrind, !$bNoCoverage, $bCoverageSummary, !$bNoOptimize,
$bBackTrace, $bProfile, $iScale, $strTimeZone, !$bNoDebug, $bDebugTestTrace,
$bProfile, $iScale, $strTimeZone, !$bNoDebug, $bDebugTestTrace,
$iBuildMax / $iVmMax < 1 ? 1 : int($iBuildMax / $iVmMax));
$iTestIdx++;