Core/Common: Catch and log child process creation errors

This commit is contained in:
Shauren
2024-09-23 14:17:33 +02:00
parent f3b8503ba6
commit fff12eafdf
2 changed files with 30 additions and 14 deletions

View File

@@ -20,13 +20,18 @@
#include "Log.h"
#include "Memory.h"
#include "Optional.h"
#ifndef BOOST_ALLOW_DEPRECATED_HEADERS
#define BOOST_ALLOW_DEPRECATED_HEADERS
#include <boost/process/args.hpp>
#include <boost/process/child.hpp>
#include <boost/process/env.hpp>
#include <boost/process/error.hpp>
#include <boost/process/exe.hpp>
#include <boost/process/io.hpp>
#include <boost/process/pipe.hpp>
#include <boost/process/search_path.hpp>
#undef BOOST_ALLOW_DEPRECATED_HEADERS
#endif
#include <fmt/ranges.h>
namespace bp = boost::process;
@@ -62,7 +67,7 @@ public:
~AsyncProcessResultImplementation() = default;
int StartProcess()
int32 StartProcess()
{
ASSERT(!my_child, "Process started already!");
@@ -84,15 +89,22 @@ public:
#pragma warning(pop)
#endif
if (!is_secure)
if (is_secure)
{
TC_LOG_TRACE(logger, "Starting process \"{}\" with arguments: \"{}\".",
TC_LOG_TRACE(logger, R"(Starting process "{}".)",
executable);
}
else
{
TC_LOG_TRACE(logger, R"(Starting process "{}" with arguments: "{}".)",
executable, fmt::join(args, " "));
}
// prepare file with only read permission (boost process opens with read_write)
auto inputFile = Trinity::make_unique_ptr_with_deleter(!input_file.empty() ? fopen(input_file.c_str(), "rb") : nullptr, &::fclose);
std::error_code ec;
// Start the child process
if (inputFile)
{
@@ -102,7 +114,8 @@ public:
bp::env = bp::environment(boost::this_process::environment()),
bp::std_in = inputFile.get(),
bp::std_out = outStream,
bp::std_err = errStream
bp::std_err = errStream,
bp::error = ec
);
}
else
@@ -111,12 +124,19 @@ public:
bp::exe = boost::filesystem::absolute(executable).string(),
bp::args = args,
bp::env = bp::environment(boost::this_process::environment()),
bp::std_in = boost::process::close,
bp::std_in = bp::close,
bp::std_out = outStream,
bp::std_err = errStream
bp::std_err = errStream,
bp::error = ec
);
}
if (ec)
{
TC_LOG_ERROR(logger, R"(>> Failed to start process "{}": {})", executable, ec.message());
return EXIT_FAILURE;
}
std::future<void> stdOutReader = std::async(std::launch::async, [&]
{
std::string line;
@@ -139,7 +159,6 @@ public:
}
});
std::error_code ec;
my_child->wait(ec);
int32 const result = !ec && !was_terminated ? my_child->exit_code() : EXIT_FAILURE;
my_child.reset();
@@ -147,11 +166,8 @@ public:
stdOutReader.wait();
stdErrReader.wait();
if (!is_secure)
{
TC_LOG_TRACE(logger, ">> Process \"{}\" finished with return value {}.",
executable, result);
}
TC_LOG_TRACE(logger, R"(>> Process "{}" finished with return value {}.)",
executable, result);
return result;
}
@@ -181,7 +197,7 @@ public:
}
};
int StartProcess(std::string executable, std::vector<std::string> args,
int32 StartProcess(std::string executable, std::vector<std::string> args,
std::string logger, std::string input_file, bool secure)
{
AsyncProcessResultImplementation handle(

View File

@@ -423,7 +423,7 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
args.emplace_back(database);
// Invokes a mysql process which doesn't leak credentials to logs
int const ret = Trinity::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), std::move(args),
int32 const ret = Trinity::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), std::move(args),
"sql.updates", "", true);
if (ret != EXIT_SUCCESS)