fix(launch): Fix several launch failure conditions (exceptions thrown in child.wait, and boost::split_unix) (#4390)
This commit is contained in:
parent
1d6d916b7a
commit
852dee0a68
2 changed files with 26 additions and 5 deletions
|
|
@ -40,6 +40,8 @@ using namespace std::literals;
|
||||||
|
|
||||||
namespace nvhttp {
|
namespace nvhttp {
|
||||||
|
|
||||||
|
static constexpr std::string_view EMPTY_PROPERTY_TREE_ERROR_MSG = "Property tree is empty. Probably, control flow got interrupted by an unexpected C++ exception. This is a bug in Sunshine. Moonlight-qt will report Malformed XML (missing root element)."sv;
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
namespace pt = boost::property_tree;
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
|
|
@ -816,6 +818,10 @@ namespace nvhttp {
|
||||||
auto g = util::fail_guard([&]() {
|
auto g = util::fail_guard([&]() {
|
||||||
std::ostringstream data;
|
std::ostringstream data;
|
||||||
|
|
||||||
|
if (tree.empty()) {
|
||||||
|
BOOST_LOG(error) << EMPTY_PROPERTY_TREE_ERROR_MSG;
|
||||||
|
}
|
||||||
|
|
||||||
pt::write_xml(data, tree);
|
pt::write_xml(data, tree);
|
||||||
response->write(data.str());
|
response->write(data.str());
|
||||||
response->close_connection_after_response = true;
|
response->close_connection_after_response = true;
|
||||||
|
|
@ -922,6 +928,10 @@ namespace nvhttp {
|
||||||
auto g = util::fail_guard([&]() {
|
auto g = util::fail_guard([&]() {
|
||||||
std::ostringstream data;
|
std::ostringstream data;
|
||||||
|
|
||||||
|
if (tree.empty()) {
|
||||||
|
BOOST_LOG(error) << EMPTY_PROPERTY_TREE_ERROR_MSG;
|
||||||
|
}
|
||||||
|
|
||||||
pt::write_xml(data, tree);
|
pt::write_xml(data, tree);
|
||||||
response->write(data.str());
|
response->write(data.str());
|
||||||
response->close_connection_after_response = true;
|
response->close_connection_after_response = true;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <boost/program_options/parsers.hpp>
|
#include <boost/program_options/parsers.hpp>
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/token_functions.hpp>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
|
@ -97,11 +98,17 @@ namespace proc {
|
||||||
|
|
||||||
boost::filesystem::path find_working_directory(const std::string &cmd, boost::process::v1::environment &env) {
|
boost::filesystem::path find_working_directory(const std::string &cmd, boost::process::v1::environment &env) {
|
||||||
// Parse the raw command string into parts to get the actual command portion
|
// Parse the raw command string into parts to get the actual command portion
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
try {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
auto parts = boost::program_options::split_winmain(cmd);
|
parts = boost::program_options::split_winmain(cmd);
|
||||||
#else
|
#else
|
||||||
auto parts = boost::program_options::split_unix(cmd);
|
parts = boost::program_options::split_unix(cmd);
|
||||||
#endif
|
#endif
|
||||||
|
} catch (boost::escaped_list_error &err) {
|
||||||
|
BOOST_LOG(error) << "Boost failed to parse command ["sv << cmd << "] because " << err.what();
|
||||||
|
return boost::filesystem::path();
|
||||||
|
}
|
||||||
if (parts.empty()) {
|
if (parts.empty()) {
|
||||||
BOOST_LOG(error) << "Unable to parse command: "sv << cmd;
|
BOOST_LOG(error) << "Unable to parse command: "sv << cmd;
|
||||||
return boost::filesystem::path();
|
return boost::filesystem::path();
|
||||||
|
|
@ -217,10 +224,14 @@ namespace proc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
child.wait();
|
child.wait(ec);
|
||||||
|
if (ec) {
|
||||||
|
BOOST_LOG(error) << '[' << cmd.do_cmd << "] wait failed with error code ["sv << ec << ']';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
auto ret = child.exit_code();
|
auto ret = child.exit_code();
|
||||||
if (ret != 0 && ec != std::errc::permission_denied) {
|
if (ret != 0) {
|
||||||
BOOST_LOG(error) << '[' << cmd.do_cmd << "] failed with code ["sv << ret << ']';
|
BOOST_LOG(error) << '[' << cmd.do_cmd << "] exited with code ["sv << ret << ']';
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue