Fix SunshineSvc hanging if an error occurs during startup (#598)

This commit is contained in:
Cameron Gutman 2022-12-21 15:41:48 -06:00 committed by GitHub
commit 8a99187562
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -71,38 +71,53 @@ HANDLE OpenLogFileHandle() {
// Overwrite the old sunshine.log // Overwrite the old sunshine.log
return CreateFileW(log_file_name, return CreateFileW(log_file_name,
GENERIC_WRITE, GENERIC_WRITE,
FILE_SHARE_READ, FILE_SHARE_READ,
&security_attributes, &security_attributes,
CREATE_ALWAYS, CREATE_ALWAYS,
0, 0,
NULL); NULL);
} }
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { 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); service_status_handle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, NULL);
if(service_status_handle == NULL) { if(service_status_handle == NULL) {
// Nothing we can really do here but terminate ourselves
ExitProcess(GetLastError());
return; return;
} }
auto log_file_handle = OpenLogFileHandle(); // Tell SCM we're starting
if (log_file_handle == INVALID_HANDLE_VALUE) {
return;
}
// Tell SCM we're running
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
service_status.dwServiceSpecificExitCode = 0; service_status.dwServiceSpecificExitCode = 0;
service_status.dwWin32ExitCode = NO_ERROR; service_status.dwWin32ExitCode = NO_ERROR;
service_status.dwWaitHint = 0; service_status.dwWaitHint = 0;
service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; service_status.dwControlsAccepted = 0;
service_status.dwCheckPoint = 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); SetServiceStatus(service_status_handle, &service_status);
// Loop every 3 seconds until the stop event is set or Sunshine.exe is running // 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 = {}; STARTUPINFOW startup_info = {};
startup_info.cb = sizeof(startup_info); startup_info.cb = sizeof(startup_info);
startup_info.lpDesktop = (LPWSTR)L"winsta0\\default"; startup_info.lpDesktop = (LPWSTR)L"winsta0\\default";
startup_info.dwFlags = STARTF_USESTDHANDLES; startup_info.dwFlags = STARTF_USESTDHANDLES;
startup_info.hStdInput = INVALID_HANDLE_VALUE; startup_info.hStdInput = INVALID_HANDLE_VALUE;
startup_info.hStdOutput = log_file_handle; startup_info.hStdOutput = log_file_handle;
startup_info.hStdError = log_file_handle; startup_info.hStdError = log_file_handle;
PROCESS_INFORMATION process_info; PROCESS_INFORMATION process_info;
if(!CreateProcessAsUserW(console_token, if(!CreateProcessAsUserW(console_token,
L"Sunshine.exe", L"Sunshine.exe",
NULL, NULL,
NULL, NULL,
NULL, NULL,
TRUE, TRUE,
ABOVE_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW, ABOVE_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW,
NULL, NULL,
NULL, NULL,
&startup_info, &startup_info,
&process_info)) { &process_info)) {
CloseHandle(console_token); CloseHandle(console_token);
continue; continue;
} }
@ -162,8 +177,7 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
SetServiceStatus(service_status_handle, &service_status); 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[] = { static const SERVICE_TABLE_ENTRY service_table[] = {
{ (LPSTR)SERVICE_NAME, ServiceMain }, { (LPSTR)SERVICE_NAME, ServiceMain },
{ NULL, NULL } { NULL, NULL }