From 330b0ef8ef43d8071a6ce1cf55eafd20b035bd08 Mon Sep 17 00:00:00 2001 From: loki Date: Mon, 30 Dec 2019 19:37:12 +0100 Subject: [PATCH] Fix bug causing Sunshine thinking there is still an app running after shutting down app from within the Stream --- sunshine/main.cpp | 1 + sunshine/nvhttp.cpp | 42 +++++++++++++++++------------------------- sunshine/process.cpp | 33 +++++++++++++++++++-------------- sunshine/process.h | 19 +++++++++++++------ sunshine/stream.cpp | 2 +- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/sunshine/main.cpp b/sunshine/main.cpp index 5f980044..b3e533ff 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -36,6 +36,7 @@ int main(int argc, char *argv[]) { if(!proc_opt) { return 7; } + proc::proc = std::move(*proc_opt); reed_solomon_init(); diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp index 01c101a4..23c0e335 100644 --- a/sunshine/nvhttp.cpp +++ b/sunshine/nvhttp.cpp @@ -87,7 +87,6 @@ enum class op_e { REMOVE }; -std::int64_t current_appid { -1 }; std::string local_ip; net::net_e origin_pin_allowed; @@ -448,7 +447,8 @@ void serverinfo(std::shared_ptr::Response> res else { tree.put("root.ExternalIP", config::nvhttp.external_ip); } - + + auto current_appid = proc::proc.running(); tree.put("root.PairStatus", pair_status); tree.put("root.currentgame", current_appid >= 0 ? current_appid + 2 : 0); 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); int x = 2; - for(auto &[name, proc] : proc::proc.get_apps()) { + for(auto &proc : proc::proc.get_apps()) { pt::ptree app; app.put("IsHdrSupported"s, 0); - app.put("AppTitle"s, name); + app.put("AppTitle"s, proc.name); app.put("ID"s, x++); 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; } - if(!proc::proc.running()) { - current_appid = -1; - } - + auto current_appid = proc::proc.running(); if(appid >= 0 && appid != current_appid) { - auto &apps = proc::proc.get_apps(); - if(appid >= apps.size()) { - tree.put("root..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); + auto err = proc::proc.execute(appid); if(err) { - tree.put("root..status_code", 500); + tree.put("root..status_code", err); tree.put("root.gamesession", 0); return; @@ -590,15 +576,15 @@ void resume(resp_https_t response, req_https_t request) { response->write(data.str()); }); - stream::launch_session_t launch_session; - - if(stream::has_session) { + auto current_appid = proc::proc.running(); + if(current_appid == -1 || stream::has_session) { tree.put("root.resume", 0); tree.put("root..status_code", 503); return; } + stream::launch_session_t launch_session; // Needed to determine if session must be closed when no process is running in proc::proc 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()); }); + if(proc::proc.running() == -1) { + tree.put("root.cancel", 1); + tree.put("root..status_code", 200); + + return; + } + if(stream::has_session) { tree.put("root..status_code", 503); tree.put("root.cancel", 0); @@ -636,7 +629,6 @@ void cancel(resp_https_t response, req_https_t request) { } proc::proc.terminate(); - current_appid = -1; tree.put("root.cancel", 1); tree.put("root..status_code", 200); diff --git a/sunshine/process.cpp b/sunshine/process.cpp index 6d5bf2b6..cd3c7b44 100644 --- a/sunshine/process.cpp +++ b/sunshine/process.cpp @@ -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); } -int proc_t::execute(const std::string &name) { - auto it = _name_to_proc.find(name); +int proc_t::execute(int app_id) { + 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 terminate(); - if(it == std::end(_name_to_proc)) { - std::cout << "Error: Couldn't find ["sv << name << ']' << std::endl; - return 404; - } - - auto &proc = it->second; + _app_id = app_id; + auto &proc = _apps[app_id]; _undo_begin = std::begin(proc.prep_cmds); _undo_it = _undo_begin; @@ -102,8 +102,12 @@ int proc_t::execute(const std::string &name) { return 0; } -bool proc_t::running() { - return _process.running(); +int proc_t::running() { + if(_process.running()) { + return _app_id; + } + + return -1; } void proc_t::terminate() { @@ -142,8 +146,8 @@ void proc_t::terminate() { _pipe.reset(); } -const std::unordered_map &proc_t::get_apps() const { - return _name_to_proc; +const std::vector &proc_t::get_apps() const { + return _apps; } proc_t::~proc_t() { @@ -221,7 +225,7 @@ std::optional parse(const std::string& file_name) { auto this_env = boost::this_process::environment(); - std::unordered_map apps; + std::vector apps; for(auto &[_,app_node] : apps_node) { proc::ctx_t ctx; @@ -255,9 +259,10 @@ std::optional parse(const std::string& file_name) { ctx.cmd = "sh -c \"while true; do sleep 10000; done;\""; } + ctx.name = std::move(name); 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(); diff --git a/sunshine/process.h b/sunshine/process.h index 6c467737..df24bbcf 100644 --- a/sunshine/process.h +++ b/sunshine/process.h @@ -37,6 +37,7 @@ struct cmd_t { struct ctx_t { std::vector prep_cmds; + std::string name; std::string cmd; std::string output; }; @@ -47,21 +48,27 @@ public: proc_t( boost::process::environment &&env, - std::unordered_map &&name_to_proc) : + std::vector &&apps) : _env(std::move(env)), - _name_to_proc(std::move(name_to_proc)) {} + _apps(std::move(apps)) {} - int execute(const std::string &name); - bool running(); + int execute(int app_id); + + /** + * @return _app_id if a process is running, otherwise returns -1 + */ + int running(); ~proc_t(); - const std::unordered_map &get_apps() const; + const std::vector &get_apps() const; void terminate(); private: + int _app_id; + boost::process::environment _env; - std::unordered_map _name_to_proc; + std::vector _apps; boost::process::child _process; boost::process::group _process_handle; diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp index 6d0ad948..01b4ec0f 100644 --- a/sunshine/stream.cpp +++ b/sunshine/stream.cpp @@ -549,7 +549,7 @@ void controlThread(video::idr_event_t idr_events) { 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::uint16_t reason = 0x0100;