Stop the service if the user quits via the tray icon

This commit is contained in:
Cameron Gutman 2023-04-15 17:51:32 -05:00
parent dd6fcbd7b8
commit f51876893e
5 changed files with 56 additions and 13 deletions

View File

@ -107,6 +107,31 @@ namespace version {
}
} // namespace version
namespace lifetime {
static std::atomic_int desired_exit_code;
/**
* @brief Terminates Sunshine gracefully with the provided exit code
* @param exit_code The exit code to return from main()
* @param async Specifies whether our termination will be non-blocking
*/
void
exit_sunshine(int exit_code, bool async) {
// Store the exit code of the first exit_sunshine() call
int zero = 0;
desired_exit_code.compare_exchange_strong(zero, exit_code);
// Raise SIGINT to start termination
std::raise(SIGINT);
// Termination will happen asynchronously, but the caller may
// have wanted synchronous behavior.
while (!async) {
std::this_thread::sleep_for(1s);
}
}
} // namespace lifetime
/**
* @brief Flush the log.
*
@ -159,13 +184,9 @@ LRESULT CALLBACK
SessionMonitorWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_ENDSESSION: {
// Raise a SIGINT to trigger our cleanup logic and terminate ourselves
// Terminate ourselves with a blocking exit call
std::cout << "Received WM_ENDSESSION"sv << std::endl;
std::raise(SIGINT);
// The signal handling is asynchronous, so we will wait here to be terminated.
// If for some reason we don't terminate in a few seconds, Windows will kill us.
SuspendThread(GetCurrentThread());
lifetime::exit_sunshine(0, false);
return 0;
}
default:
@ -376,7 +397,7 @@ main(int argc, char *argv[]) {
// FIXME: Temporary workaround: Simple-Web_server needs to be updated or replaced
if (shutdown_event->peek()) {
return 0;
return lifetime::desired_exit_code;
}
std::thread httpThread { nvhttp::start };
@ -395,7 +416,7 @@ main(int argc, char *argv[]) {
system_tray::end_tray();
#endif
return 0;
return lifetime::desired_exit_code;
}
/**

View File

@ -79,4 +79,10 @@ namespace mail {
#undef MAIL
} // namespace mail
namespace lifetime {
void
exit_sunshine(int exit_code, bool async);
} // namespace lifetime
#endif // SUNSHINE_MAIN_H

View File

@ -727,9 +727,10 @@ namespace platf {
bool
restart() {
// Raise SIGINT to trigger the graceful exit logic. The service will
// restart us in a few seconds.
std::raise(SIGINT);
// 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.
lifetime::exit_sunshine(0, true);
return true;
}

View File

@ -131,7 +131,15 @@ namespace system_tray {
tray_quit_cb(struct tray_menu *item) {
BOOST_LOG(info) << "Quiting from system tray"sv;
std::raise(SIGINT);
#ifdef _WIN32
// If we're running in a service, return a special status to
// tell it to terminate too, otherwise it will just respawn us.
if (GetConsoleWindow() == NULL) {
lifetime::exit_sunshine(ERROR_SHUTDOWN_IN_PROGRESS, false);
}
#endif
lifetime::exit_sunshine(0, false);
}
// Tray menu

View File

@ -301,9 +301,16 @@ ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
}
break;
case WAIT_OBJECT_0 + 1:
case WAIT_OBJECT_0 + 1: {
// Sunshine terminated itself.
DWORD exit_code;
if (GetExitCodeProcess(process_info.hProcess, &exit_code) && exit_code == ERROR_SHUTDOWN_IN_PROGRESS) {
// Sunshine is asking for us to shut down, so gracefully stop ourselves.
SetEvent(stop_event);
}
break;
}
}
CloseHandle(process_info.hThread);