Fix bug causing Sunshine thinking there is still an app running after shutting down app from within the Stream

This commit is contained in:
loki 2019-12-30 19:37:12 +01:00
parent 94e1dc903e
commit 330b0ef8ef
5 changed files with 51 additions and 46 deletions

View File

@ -36,6 +36,7 @@ int main(int argc, char *argv[]) {
if(!proc_opt) { if(!proc_opt) {
return 7; return 7;
} }
proc::proc = std::move(*proc_opt); proc::proc = std::move(*proc_opt);
reed_solomon_init(); reed_solomon_init();

View File

@ -87,7 +87,6 @@ enum class op_e {
REMOVE REMOVE
}; };
std::int64_t current_appid { -1 };
std::string local_ip; std::string local_ip;
net::net_e origin_pin_allowed; net::net_e origin_pin_allowed;
@ -448,7 +447,8 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
else { else {
tree.put("root.ExternalIP", config::nvhttp.external_ip); tree.put("root.ExternalIP", config::nvhttp.external_ip);
} }
auto current_appid = proc::proc.running();
tree.put("root.PairStatus", pair_status); tree.put("root.PairStatus", pair_status);
tree.put("root.currentgame", current_appid >= 0 ? current_appid + 2 : 0); tree.put("root.currentgame", current_appid >= 0 ? current_appid + 2 : 0);
tree.put("root.state", "_SERVER_BUSY"); tree.put("root.state", "_SERVER_BUSY");
@ -491,11 +491,11 @@ void applist(resp_https_t response, req_https_t request) {
desktop.put("ID"s, 1); desktop.put("ID"s, 1);
int x = 2; int x = 2;
for(auto &[name, proc] : proc::proc.get_apps()) { for(auto &proc : proc::proc.get_apps()) {
pt::ptree app; pt::ptree app;
app.put("IsHdrSupported"s, 0); app.put("IsHdrSupported"s, 0);
app.put("AppTitle"s, name); app.put("AppTitle"s, proc.name);
app.put("ID"s, x++); app.put("ID"s, x++);
apps.push_back(std::make_pair("App", std::move(app))); apps.push_back(std::make_pair("App", std::move(app)));
@ -527,25 +527,11 @@ void launch(resp_https_t response, req_https_t request) {
return; return;
} }
if(!proc::proc.running()) { auto current_appid = proc::proc.running();
current_appid = -1;
}
if(appid >= 0 && appid != current_appid) { if(appid >= 0 && appid != current_appid) {
auto &apps = proc::proc.get_apps(); auto err = proc::proc.execute(appid);
if(appid >= apps.size()) {
tree.put("root.<xmlattr>.status_code", 404);
tree.put("root.gamesession", 0);
return;
}
auto pos = std::begin(apps);
std::advance(pos, appid);
auto err = proc::proc.execute(pos->first);
if(err) { if(err) {
tree.put("root.<xmlattr>.status_code", 500); tree.put("root.<xmlattr>.status_code", err);
tree.put("root.gamesession", 0); tree.put("root.gamesession", 0);
return; return;
@ -590,15 +576,15 @@ void resume(resp_https_t response, req_https_t request) {
response->write(data.str()); response->write(data.str());
}); });
stream::launch_session_t launch_session; auto current_appid = proc::proc.running();
if(current_appid == -1 || stream::has_session) {
if(stream::has_session) {
tree.put("root.resume", 0); tree.put("root.resume", 0);
tree.put("root.<xmlattr>.status_code", 503); tree.put("root.<xmlattr>.status_code", 503);
return; return;
} }
stream::launch_session_t launch_session;
// Needed to determine if session must be closed when no process is running in proc::proc // Needed to determine if session must be closed when no process is running in proc::proc
launch_session.has_process = current_appid >= 0; launch_session.has_process = current_appid >= 0;
@ -628,6 +614,13 @@ void cancel(resp_https_t response, req_https_t request) {
response->write(data.str()); response->write(data.str());
}); });
if(proc::proc.running() == -1) {
tree.put("root.cancel", 1);
tree.put("root.<xmlattr>.status_code", 200);
return;
}
if(stream::has_session) { if(stream::has_session) {
tree.put("root.<xmlattr>.status_code", 503); tree.put("root.<xmlattr>.status_code", 503);
tree.put("root.cancel", 0); tree.put("root.cancel", 0);
@ -636,7 +629,6 @@ void cancel(resp_https_t response, req_https_t request) {
} }
proc::proc.terminate(); proc::proc.terminate();
current_appid = -1;
tree.put("root.cancel", 1); tree.put("root.cancel", 1);
tree.put("root.<xmlattr>.status_code", 200); tree.put("root.<xmlattr>.status_code", 200);

View File

@ -41,18 +41,18 @@ int exe(const std::string &cmd, bp::environment &env, file_t &file, std::error_c
return bp::system(cmd, env, bp::std_out > file.get(), bp::std_err > file.get(), ec); return bp::system(cmd, env, bp::std_out > file.get(), bp::std_err > file.get(), ec);
} }
int proc_t::execute(const std::string &name) { int proc_t::execute(int app_id) {
auto it = _name_to_proc.find(name); if(app_id >= _apps.size()) {
std::cout << "Error: Couldn't find app with ID ["sv << app_id << ']' << std::endl;
return 404;
}
// Ensure starting from a clean slate // Ensure starting from a clean slate
terminate(); terminate();
if(it == std::end(_name_to_proc)) { _app_id = app_id;
std::cout << "Error: Couldn't find ["sv << name << ']' << std::endl; auto &proc = _apps[app_id];
return 404;
}
auto &proc = it->second;
_undo_begin = std::begin(proc.prep_cmds); _undo_begin = std::begin(proc.prep_cmds);
_undo_it = _undo_begin; _undo_it = _undo_begin;
@ -102,8 +102,12 @@ int proc_t::execute(const std::string &name) {
return 0; return 0;
} }
bool proc_t::running() { int proc_t::running() {
return _process.running(); if(_process.running()) {
return _app_id;
}
return -1;
} }
void proc_t::terminate() { void proc_t::terminate() {
@ -142,8 +146,8 @@ void proc_t::terminate() {
_pipe.reset(); _pipe.reset();
} }
const std::unordered_map<std::string, ctx_t> &proc_t::get_apps() const { const std::vector<ctx_t> &proc_t::get_apps() const {
return _name_to_proc; return _apps;
} }
proc_t::~proc_t() { proc_t::~proc_t() {
@ -221,7 +225,7 @@ std::optional<proc::proc_t> parse(const std::string& file_name) {
auto this_env = boost::this_process::environment(); auto this_env = boost::this_process::environment();
std::unordered_map<std::string, proc::ctx_t> apps; std::vector<proc::ctx_t> apps;
for(auto &[_,app_node] : apps_node) { for(auto &[_,app_node] : apps_node) {
proc::ctx_t ctx; proc::ctx_t ctx;
@ -255,9 +259,10 @@ std::optional<proc::proc_t> parse(const std::string& file_name) {
ctx.cmd = "sh -c \"while true; do sleep 10000; done;\""; ctx.cmd = "sh -c \"while true; do sleep 10000; done;\"";
} }
ctx.name = std::move(name);
ctx.prep_cmds = std::move(prep_cmds); ctx.prep_cmds = std::move(prep_cmds);
apps.emplace(std::move(name), std::move(ctx)); apps.emplace_back(std::move(ctx));
} }
bp::environment env = boost::this_process::environment(); bp::environment env = boost::this_process::environment();

View File

@ -37,6 +37,7 @@ struct cmd_t {
struct ctx_t { struct ctx_t {
std::vector<cmd_t> prep_cmds; std::vector<cmd_t> prep_cmds;
std::string name;
std::string cmd; std::string cmd;
std::string output; std::string output;
}; };
@ -47,21 +48,27 @@ public:
proc_t( proc_t(
boost::process::environment &&env, boost::process::environment &&env,
std::unordered_map<std::string, ctx_t> &&name_to_proc) : std::vector<ctx_t> &&apps) :
_env(std::move(env)), _env(std::move(env)),
_name_to_proc(std::move(name_to_proc)) {} _apps(std::move(apps)) {}
int execute(const std::string &name); int execute(int app_id);
bool running();
/**
* @return _app_id if a process is running, otherwise returns -1
*/
int running();
~proc_t(); ~proc_t();
const std::unordered_map<std::string, ctx_t> &get_apps() const; const std::vector<ctx_t> &get_apps() const;
void terminate(); void terminate();
private: private:
int _app_id;
boost::process::environment _env; boost::process::environment _env;
std::unordered_map<std::string, ctx_t> _name_to_proc; std::vector<ctx_t> _apps;
boost::process::child _process; boost::process::child _process;
boost::process::group _process_handle; boost::process::group _process_handle;

View File

@ -549,7 +549,7 @@ void controlThread(video::idr_event_t idr_events) {
stop(session); stop(session);
} }
if(session.has_process && !proc::proc.running()) { if(session.has_process && proc::proc.running() == -1) {
std::cout << "Process terminated"sv << std::endl; std::cout << "Process terminated"sv << std::endl;
std::uint16_t reason = 0x0100; std::uint16_t reason = 0x0100;