From 8a99187562c1d535d401ac61691256731e99749a Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 21 Dec 2022 15:41:48 -0600 Subject: [PATCH] Fix SunshineSvc hanging if an error occurs during startup (#598) --- tools/sunshinesvc.cpp | 88 +++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/tools/sunshinesvc.cpp b/tools/sunshinesvc.cpp index 13a6b514..3a7d2673 100644 --- a/tools/sunshinesvc.cpp +++ b/tools/sunshinesvc.cpp @@ -71,38 +71,53 @@ HANDLE OpenLogFileHandle() { // Overwrite the old sunshine.log return CreateFileW(log_file_name, - GENERIC_WRITE, - FILE_SHARE_READ, - &security_attributes, - CREATE_ALWAYS, - 0, - NULL); + GENERIC_WRITE, + FILE_SHARE_READ, + &security_attributes, + CREATE_ALWAYS, + 0, + NULL); } VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { - stop_event = CreateEventA(NULL, TRUE, FALSE, NULL); - if(stop_event == NULL) { - return; - } - service_status_handle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, NULL); if(service_status_handle == NULL) { + // Nothing we can really do here but terminate ourselves + ExitProcess(GetLastError()); return; } - auto log_file_handle = OpenLogFileHandle(); - if (log_file_handle == INVALID_HANDLE_VALUE) { - return; - } - - // Tell SCM we're running + // Tell SCM we're starting service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwServiceSpecificExitCode = 0; service_status.dwWin32ExitCode = NO_ERROR; service_status.dwWaitHint = 0; - service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + service_status.dwControlsAccepted = 0; service_status.dwCheckPoint = 0; - service_status.dwCurrentState = SERVICE_RUNNING; + service_status.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(service_status_handle, &service_status); + + stop_event = CreateEventA(NULL, TRUE, FALSE, NULL); + if(stop_event == NULL) { + // Tell SCM we failed to start + service_status.dwWin32ExitCode = GetLastError(); + service_status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(service_status_handle, &service_status); + return; + } + + auto log_file_handle = OpenLogFileHandle(); + if(log_file_handle == INVALID_HANDLE_VALUE) { + // Tell SCM we failed to start + service_status.dwWin32ExitCode = GetLastError(); + service_status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(service_status_handle, &service_status); + return; + } + + // Tell SCM we're running (and stoppable now) + service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + service_status.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(service_status_handle, &service_status); // Loop every 3 seconds until the stop event is set or Sunshine.exe is running @@ -113,25 +128,25 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { } STARTUPINFOW startup_info = {}; - startup_info.cb = sizeof(startup_info); - startup_info.lpDesktop = (LPWSTR)L"winsta0\\default"; - startup_info.dwFlags = STARTF_USESTDHANDLES; - startup_info.hStdInput = INVALID_HANDLE_VALUE; - startup_info.hStdOutput = log_file_handle; - startup_info.hStdError = log_file_handle; + startup_info.cb = sizeof(startup_info); + startup_info.lpDesktop = (LPWSTR)L"winsta0\\default"; + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = INVALID_HANDLE_VALUE; + startup_info.hStdOutput = log_file_handle; + startup_info.hStdError = log_file_handle; PROCESS_INFORMATION process_info; if(!CreateProcessAsUserW(console_token, - L"Sunshine.exe", - NULL, - NULL, - NULL, - TRUE, - ABOVE_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW, - NULL, - NULL, - &startup_info, - &process_info)) { + L"Sunshine.exe", + NULL, + NULL, + NULL, + TRUE, + ABOVE_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW, + NULL, + NULL, + &startup_info, + &process_info)) { CloseHandle(console_token); continue; } @@ -162,8 +177,7 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { SetServiceStatus(service_status_handle, &service_status); } -int main(int argc, char* argv[]) -{ +int main(int argc, char *argv[]) { static const SERVICE_TABLE_ENTRY service_table[] = { { (LPSTR)SERVICE_NAME, ServiceMain }, { NULL, NULL }