/*********************************************************************************************************************************** Execute main function in Perl ***********************************************************************************************************************************/ int perlExec(void) { FUNCTION_LOG_VOID(logLevelDebug); // Initialize Perl perlInit(); // Run perl main function perlEval(perlMain()); // Return result code int code = (int)SvIV(get_sv("iResult", 0)); bool errorC = (int)SvIV(get_sv("bErrorC", 0)); char *message = SvPV_nolen(get_sv("strMessage", 0)); // {uncovered - internal Perl macro branch} if (code >= errorTypeCode(&AssertError)) // {uncovered - success tested in integration} { if (errorC) // {+uncovered} RETHROW(); // {+uncovered} else THROW_CODE(code, strlen(message) == 0 ? PERL_EMBED_ERROR : message); // {+uncovered} } FUNCTION_LOG_RETURN(INT, code); // {+uncovered} }
/*********************************************************************************************************************************** Free Perl objects Don't bother freeing Perl itself since we are about to exit. ***********************************************************************************************************************************/ void perlFree(int result) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(INT, result); FUNCTION_TEST_END(); if (my_perl != NULL) perlEval(strNewFmt(PGBACKREST_MAIN "Cleanup(%d)", result)); FUNCTION_TEST_RETURN_VOID(); }
int perlExec(void) { FUNCTION_LOG_VOID(logLevelDebug); // Initialize Perl perlInit(); // Run perl main function perlEval(perlMain()); // Return result code int code = (int)SvIV(get_sv("iResult", 0)); // {uncoverable_branch - Perl macro} bool errorC = (int)SvIV(get_sv("bErrorC", 0)); // {uncoverable_branch - Perl macro} char *message = SvPV_nolen(get_sv("strMessage", 0)); // {uncoverable_branch - Perl macro} FUNCTION_LOG_RETURN(INT, perlExecResult(code, errorC, message)); }
/*********************************************************************************************************************************** Initialize Perl ***********************************************************************************************************************************/ static void perlInit(void) { FUNCTION_TEST_VOID(); if (!my_perl) { // Initialize Perl with dummy args and environment int argc = 1; const char *argv[1] = {strPtr(cfgExe())}; const char *env[1] = {NULL}; PERL_SYS_INIT3(&argc, (char ***)&argv, (char ***)&env); // Create the interpreter const char *embedding[] = {"", "-e", "0"}; my_perl = perl_alloc(); perl_construct(my_perl); // Don't let $0 assignment update the proctitle or embedding[0] PL_origalen = 1; // Start the interpreter perl_parse(my_perl, xs_init, 3, (char **)embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); // Use customer loader to get all embedded modules eval_pv("splice(@INC, 0, 0, " LOADER_SUB ");", true); // Now that the custom loader is installed, load the main module; eval_pv("use " PGBACKREST_MODULE ";", true); // Set config data -- this is done separately to avoid it being included in stack traces perlEval(strNewFmt(PGBACKREST_MAIN "ConfigSet('%s', '%s')", strPtr(cfgExe()), strPtr(perlOptionJson()))); } FUNCTION_TEST_RETURN_VOID(); }