Implement restart support for all platforms

This commit is contained in:
Cameron Gutman
2023-04-23 18:09:13 -05:00
parent 4668ff59e5
commit 50f689ff80
10 changed files with 128 additions and 82 deletions

View File

@@ -399,9 +399,7 @@ namespace platf {
void
streaming_will_stop();
bool
restart_supported();
bool
void
restart();
struct batched_send_info_t {

View File

@@ -193,16 +193,34 @@ namespace platf {
// Nothing to do
}
bool
restart_supported() {
// Restart not supported yet
return false;
void
restart_on_exit() {
char executable[PATH_MAX];
ssize_t len = readlink("/proc/self/exe", executable, PATH_MAX - 1);
if (len == -1) {
BOOST_LOG(fatal) << "readlink() failed: "sv << errno;
return;
}
executable[len] = '\0';
// ASIO doesn't use O_CLOEXEC, so we have to close all fds ourselves
int openmax = (int) sysconf(_SC_OPEN_MAX);
for (int fd = STDERR_FILENO + 1; fd < openmax; fd++) {
close(fd);
}
// Re-exec ourselves with the same arguments
if (execv(executable, lifetime::get_argv()) < 0) {
BOOST_LOG(fatal) << "execv() failed: "sv << errno;
return;
}
}
bool
void
restart() {
// Restart not supported yet
return false;
// Gracefully clean up and restart ourselves instead of exiting
atexit(restart_on_exit);
lifetime::exit_sunshine(0, true);
}
bool

View File

@@ -3,6 +3,7 @@
#include <dlfcn.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <mach-o/dyld.h>
#include <net/if_dl.h>
#include <pwd.h>
@@ -192,16 +193,33 @@ namespace platf {
// Nothing to do
}
bool
restart_supported() {
// Restart not supported yet
return false;
void
restart_on_exit() {
char executable[2048];
uint32_t size = sizeof(executable);
if (_NSGetExecutablePath(executable, &size) < 0) {
BOOST_LOG(fatal) << "NSGetExecutablePath() failed: "sv << errno;
return;
}
// ASIO doesn't use O_CLOEXEC, so we have to close all fds ourselves
int openmax = (int) sysconf(_SC_OPEN_MAX);
for (int fd = STDERR_FILENO + 1; fd < openmax; fd++) {
close(fd);
}
// Re-exec ourselves with the same arguments
if (execv(executable, lifetime::get_argv()) < 0) {
BOOST_LOG(fatal) << "execv() failed: "sv << errno;
return;
}
}
bool
void
restart() {
// Restart not supported yet
return false;
// Gracefully clean up and restart ourselves instead of exiting
atexit(restart_on_exit);
lifetime::exit_sunshine(0, true);
}
bool

View File

@@ -809,19 +809,49 @@ namespace platf {
}
}
bool
restart_supported() {
// Restart is supported if we're running from the service
return (GetConsoleWindow() == NULL);
void
restart_on_exit() {
STARTUPINFOEXW startup_info {};
startup_info.StartupInfo.cb = sizeof(startup_info);
WCHAR executable[MAX_PATH];
if (GetModuleFileNameW(NULL, executable, ARRAYSIZE(executable)) == 0) {
auto winerr = GetLastError();
BOOST_LOG(fatal) << "Failed to get Sunshine path: "sv << winerr;
return;
}
PROCESS_INFORMATION process_info;
if (!CreateProcessW(executable,
GetCommandLineW(),
nullptr,
nullptr,
false,
CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT,
nullptr,
nullptr,
(LPSTARTUPINFOW) &startup_info,
&process_info)) {
auto winerr = GetLastError();
BOOST_LOG(fatal) << "Unable to restart Sunshine: "sv << winerr;
return;
}
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
}
bool
void
restart() {
// Gracefully exit. The service will restart us in a few seconds.
// We use an async exit call here because we can't block the
// HTTP thread or we'll hang shutdown.
// If we're running standalone, we have to respawn ourselves via CreateProcess().
// If we're running from the service, we should just exit and let it respawn us.
if (GetConsoleWindow() != NULL) {
// Avoid racing with the new process by waiting until we're exiting to start it.
atexit(restart_on_exit);
}
// We use an async exit call here because we can't block the HTTP thread or we'll hang shutdown.
lifetime::exit_sunshine(0, true);
return true;
}
SOCKADDR_IN