{"record":{"id":"ba06446c82240983","repo":"java-native-access/jna","slug":"service-stop-exceeded-timeout-time-of-d-ms","errorCode":null,"errorMessage":"Service stop exceeded timeout time of %d ms","messagePattern":"Service stop exceeded timeout time of (.+?) ms","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/W32Service.java","lineNumber":244,"sourceCode":"    public void stopService(long timeout) {\n        long startTime = System.currentTimeMillis();\n        waitForNonPendingState();\n        // If the service is already stopped - return\n        if (queryStatus().dwCurrentState == Winsvc.SERVICE_STOPPED) {\n            return;\n        }\n        SERVICE_STATUS status = new SERVICE_STATUS();\n        if (!Advapi32.INSTANCE.ControlService(_handle, SERVICE_CONTROL_STOP, status)) {\n            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n        }\n        // This following the sample from the MSDN\n        // the previouos implementation queried the service status and\n        // failed if the application did not correctly update its state\n        while (status.dwCurrentState != Winsvc.SERVICE_STOPPED) {\n            long msRemainingBeforeTimeout = timeout - (System.currentTimeMillis() - startTime);\n\n            if (msRemainingBeforeTimeout < 0) {\n                throw new RuntimeException(String.format(\"Service stop exceeded timeout time of %d ms\", timeout));\n            }\n\n            long dwWaitTime = Math.min(sanitizeWaitTime(status.dwWaitHint), msRemainingBeforeTimeout);\n\n            try {\n                Thread.sleep(dwWaitTime);\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n            if (!Advapi32.INSTANCE.QueryServiceStatus(_handle, status)) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n        }\n    }\n\n    /**\n     * Continue service.\n     */","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/W32Service.java#L226-L262","documentation":"W32Service.stopService() polls the service status in a loop until it reports SERVICE_STOPPED. If the wall-clock time since the stop request exceeds the caller-supplied timeout while the service is still not STOPPED, it throws this RuntimeException so the caller knows the stop did not complete in time.","triggerScenarios":"Calling stopService(timeoutMs) on a Windows service whose dwCurrentState stays non-STOPPED past the deadline — e.g. a service with a long OnStop handler, a hung/stuck service, or a timeout set too short for the service's shutdown work.","commonSituations":"Services that block shutdown waiting on worker threads or network I/O; SCM wait-hint values that understate real stop time; passing small (e.g. 1000 ms) timeouts to services that take tens of seconds to stop; debugging services in a paused or stop-pending state.","solutions":["Increase the timeout argument to stopService to a value larger than the service's realistic shutdown time.","Fix the service itself so its stop handler exits promptly (signal worker threads, use a cancellation mechanism).","Check the service state manually (sc query / services.msc) to see whether it is stuck in STOP_PENDING and needs force-kill.","Catch the RuntimeException and fall back to killing the process or waiting longer with a fresh request."],"exampleFix":"// before\nservice.stopService(1000);\n// after\nservice.stopService(60_000); // allow slow shutdowns","handlingStrategy":"try-catch","validationCode":"Winsvc.SERVICE_STATUS st = service.queryStatus();\nif (st.dwCurrentState == Winsvc.SERVICE_STOPPED) { /* already stopped */ }\n// choose timeout generously, e.g. max(30s, 2 * st.dwWaitHint)","typeGuard":null,"tryCatchPattern":"try {\n    service.stopService(timeoutMs);\n} catch (RuntimeException e) {\n    Winsvc.SERVICE_STATUS st = service.queryStatus();\n    if (st.dwCurrentState != Winsvc.SERVICE_STOPPED) { /* escalate: kill or alert */ }\n}","preventionTips":["Set timeouts well above the service's known shutdown time.","Check dwWaitHint from queryStatus before choosing the timeout.","Monitor services that routinely hit stop timeouts — fix the service, not the caller."],"tags":["windows","service","timeout"],"backgroundTag":"request-timeout","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}