Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
 
root / assets / surprised.png
Author[]google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.c...> 2025-12-03 14:48 UTC
Committer[]Andy Green <andy@warmcat.com> 2025-12-03 14:58 UTC
Tree063b6ddb8415ba8f22bfed7733b2d415068d0a8f   Raw Patch
 
Add native Windows Service support to sai-builder
Add native Windows Service support to sai-builder

Refactors the main application loop into `saib_app_run` to allow execution from a service context.
Adds `b-win32-service.c` to implement Windows Service API hooks (`ServiceMain`, `ServiceCtrlHandler`).
Updates `CMakeLists.txt` to include the service support on Windows builds.
Ensures command-line arguments are propagated correctly when running as a service.
diff --git a/src/builder/CMakeLists.txt b/src/builder/CMakeLists.txt index 1b1f9a3..8768b0d 100644 --- a/src/builder/CMakeLists.txt +++ b/src/builder/CMakeLists.txt @@ -3,6 +3,7 @@ set(CPACK_DEBIAN_BUILDER_PACKAGE_NAME "sai-builder") main() and captured in g_argc/g_argv. + * We use these captured arguments to start the app, ensuring configuration is preserved. + */ + + g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); + + if (g_StatusHandle == NULL) + { + return; + } + + ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus)); + g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + g_ServiceStatus.dwControlsAccepted = 0; + g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; + g_ServiceStatus.dwWin32ExitCode = 0; + g_ServiceStatus.dwServiceSpecificExitCode = 0; + g_ServiceStatus.dwCheckPoint = 0; + + if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) + { + return; + } + + /* + * We don't need a separate worker thread because ServiceMain runs in its own thread + * and we can block here. However, we need to handle the control requests. + */ + + g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; + g_ServiceStatus.dwWin32ExitCode = 0; + g_ServiceStatus.dwCheckPoint = 0; + + if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) + { + return; + } + + /* Run the app using the arguments passed to the process */ + rc = saib_app_run(g_argc, g_argv); + + g_ServiceStatus.dwControlsAccepted = 0; + g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; + + if (rc) { + g_ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; + g_ServiceStatus.dwServiceSpecificExitCode = (DWORD)rc; + } else { + g_ServiceStatus.dwWin32ExitCode = 0; + } + + g_ServiceStatus.dwCheckPoint = 3; + + SetServiceStatus(g_StatusHandle, &g_ServiceStatus); +} + +VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode) +{ + switch (CtrlCode) + { + case SERVICE_CONTROL_STOP: + if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING) + break; + + g_ServiceStatus.dwControlsAccepted = 0; + g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + g_ServiceStatus.dwWin32ExitCode = 0; + g_ServiceStatus.dwCheckPoint = 4; + + SetServiceStatus(g_StatusHandle, &g_ServiceStatus); + + saib_app_stop(); + break; + + default: + break; + } +} +#endif
Page fetched 0s ago, creation time: 9ms (vhost etag hits: 0%, cache hits: 0%)