I'm trying to start a service with StartService method. According to the documentation:
StartService will block for 30 seconds if any service is busy handling a control code.
How can I change this timeout value?
You cannot change the timeout. It is builtin to the SCM, and contractually obligated by the documentation to be 30 seconds only.
UPDATE: Apparently, you can change the timeout after all. But only in the Registry, not in code. And it requires a reboot to take effect. See How do I increase windows service startup timeout on Server Fault.
It is the responsibility of each service to respond to the SCM in a timely manner. During a start request, a service needs to call StartServiceCtrlDispatcher() as soon as possible. If it needs a lengthy startup, it should be starting the dispatcher quickly, then entering a PENDING state and report updated status at regular intervals until ready.
Related
I have developed a Win32 service (SERVICE_WIN32_OWN_PROCESS) in C++ for Windows 10. It fails to start once in a while, with the following messages in the event log:
A timeout was reached (45000 milliseconds) while waiting for the MyService service to connect.
The MyService service failed to start due to the following error:
The service did not respond to the start or control request in a timely fashion.
What kind of timeout is happening here?
I know that when a service starts up, there is a timeout of 30 seconds from the start of the executable to the call of StartServiceCtrlDispatcher(). I have a log statement just before the call to StartServiceCtrlDispatcher(), but I do not see it. Unfortunately, I do not have any log statements at the point where the service starts up. In between startup and StartServiceCtrlDispatcher(), I have a bit of initialization, but nothing that I would expect to take 30 seconds to finish.
My service never reaches StartServiceCtrlDispatcher() and I have not seen traces in the event log that it crashes.
So, why does the error message mention a timeout of 45 seconds and not 30 seconds? What does this timeout represent?
Edit: For now I am mostly interested if other persons have experienced similar timeout and if they have figured out the reason. I need to debug my code, but I hope that someone might be able to give a direction in which I could concentrate my debugging in. Later I might need specific help with my code when I know where to look :-)
Edit: Microsoft describes many kinds of timeout in their API documentation for services. But I have not seen any mentioning of a 45 seconds timeout even if I have read all the API calls that I am using.
Note: I have not modified any timeouts in the system/registry, if such a thing is possible.
Edit:
Notes about my service.
The issue happens on a users pc that I do not have direct access to.
My service starts up correctly most of the time, but when it fails, it might be during a windows update under boot-up, that causes it.
In a virtual machine with a debug version of my service it takes less than 2 seconds from start of executable to call of StartServiceCtrlDispatcher(). That sounds reasonable. Far below 30 seconds and 45 seconds.
I have in my development environment tried to add a delay (sleep) between start and StartServiceCtrlDispatcher() of greater than 30 seconds. This gave me the standard message about a 30000 miliseconds timeout. Not 45000!
I have tried to force a crash between start and StartServiceCtrlDispatcher(). This gave me a "Application Error" event log entry about the crash and a standard 30000 seconds timeout. Not 45000! On the problem PCs eventlog I have not noticed any "Application Error" when the startup failed.
I need the service to stop long enough. Approximately 5-10 minutes. Now on windows 10, my service system kills after 60 seconds without waiting for it to finish correctly. Saw a similar issue for C# using the net function RequestAdditionalTime. But I need a C++ implementation on the API.
setting the key value in the registry did not affect
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillService set to 300000
You should not mess with global registry settings.
When stopping your service please call SetServiceStatus with SERVICE_STOP_PENDING and set dwCheckPoint and dwWaitHint to a proper value. And according to the documentation for dwWaitHint call ServServiceStatus multiple times until you are done and the service is stopped (SetServiceStatus(h, SERVICE_STOPPED, ...)).
I write a local service application using C++ and I can't find the correct way of registering for a pre-shut-down notification (for OS later than Windows XP). I believe that SERVICE_CONTROL_PRESHUTDOWN notification has been added since Vista, but when you call SetServiceStatus do we need to specify:
dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PRESHUTDOWN;
or
dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PRESHUTDOWN;
You cannot accept both a shutdown and a preshutdown if your service is correctly coded. The documentation explicitly states this.
From http://msdn.microsoft.com/en-us/library/windows/desktop/ms683241(v=vs.85).aspx:
Referring to SERVICE_CONTROL_PRESHUTDOWN:
A service that handles this notification blocks system shutdown until the service stops or the preshutdown time-out interval specified through SERVICE_PRESHUTDOWN_INFO expires.
In the same page, the section about SERVICE_CONTROL_SHUTDOWN adds:
Note that services that register for SERVICE_CONTROL_PRESHUTDOWN notifications cannot receive this notification because they have already stopped.
So, the correct way is to set the dwControlsAccepted to include either SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PRESHUTDOWN, depending on your needs, but not to both at the same time.
But do note that you probably want to accept more controls. You should always allow at least SERVICE_CONTROL_INTERROGATE, and almost certainly allow SERVICE_CONTROL_STOP, since without the latter the service cannot be stopped (e.g. in order to uninstall the software) and the process will have to be forcibly terminated (i.e. killed).
As noted by the commenters above, you will need to choose from either SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PRESHUTDOWN (Vista or later). If you are using SERVICE_ACCEPT_PRESHUTDOWN, you will need to register your service with the SCM using RegisterServiceCtrlHandlerEx instead of RegisterServiceCtrlHandler else you will not be receiving the pre-shutdown notifications. The handler prototype also changes from Handler to HandlerEx.
Another point to note is that handling pure shutdown events is limited to 5 seconds in Windows Server 2012 (and presumably Windows 8), 12 seconds in Windows 7 and Windows Server 2008, 20 seconds in Windows XP before your service is killed while stopping. This is the reason why you may need the pre-shutdown notification. You may want to change this at \\HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout.
In the comment from alexpi there is a key piece of information. I found that the service handling PRESHUTDOWN needs to update the service status with a new checkpoint number (repeatedly) before WaitToKillServiceTimeout has elapsed. My server was configured to 5000 ms and my service only updated every 12000 ms, and the server went into the SHUTDOWN phase, which caused my attempt to stop another service to return the error that the shutdown was in progress.
These two notifications seem to be different as I get it from the documentation. If what you need is really to enable your service to recieve preshutdown notification, you should go with: dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PRESHUTDOWN; But if you also want to enable your service to receive shutdown notifications, you should go with your second option.
I am trying to control a service within an application. Starting the service via StartService (MSDN) works fine, the service needs about 10 seconds to start, but after calling StartService it gives the control back to the main-application immediately.
However, when stopping the service via ControlService (MSDN) - AFAIK there is no StopService - it blocks the main-application for the complete time until the service is stopped, which takes about 10 seconds.
Start: StartServiceW( handle, 0, NULL)
Stop: ControlService( handle, SERVICE_CONTROL_STOP, status )
Is there a way for a non-blocking / asynchronously stopping of a windows service?
I would probably look at stopping the service in a new thread. That will eliminate the blocking of your main thread.
The SCM processes control requests in a serialized manner. If any service is busy processing a control request, ControlService() will be blocked until the SCM can process the new request. This is stated as much in the documentation:
The SCM processes service control notifications in a serial fashion—it
will wait for one service to complete processing a service control
notification before sending the next one. Because of this, a call to
ControlService will block for 30 seconds if any service is busy
handling a control code. If the busy service still has not returned
from its handler function when the timeout expires, ControlService
fails with ERROR_SERVICE_REQUEST_TIMEOUT.
The service is doing its cleanup in its control handler routine. That's OK for a service that will only take a fraction of a second to exit, but a service that's going to take ten seconds should definitely be setting a status of STOP_PENDING and then cleaning up asynchronously.
If this is your own service, you should correct that problem. I'd start by making sure that all of the cleanup is really necessary; for example, there's no need to free memory before stopping (unless the service is sharing a process with other services). If the cleanup really can't be made fast enough, launch a separate thread (or signal your main thread) to perform the service shutdown and set the service status to STOP_PENDING.
If this is someone else's service, the only solution is to issue the stop request from a separate thread or in a subprocess.
Is there a way to kill / re-start a long running task in AWS SWF? Sometimes some of our tasks run for a longer duration and we would like to manually kill a certain task (either via UI or programmatically) and re-start the task if possible. How to achieve this?
Console is option to manually kill workflow.
You can also set timeouts to whole workflow execution time or to individual activities. This can be set when you register your activity or when you start your activity (defaultTaskStartToCloseTimeoutSecond).
It's not clear what language you're using.
If you're using java, then you should look into Exponential Retry in Flow Framework. This make SDK restart your activity if it fails.
Long running activity is expected to heartbeat using RecordActivityTaskHeartbeat. It leads to timeout failure after short hearbeat interval instead of long task execution timeout if the activity process hangs or crashes.
The workflow code (decider) can always request activity cancellation through RequestCancelActivityTask decision. The cancellation request is returned as output of the RecordActivityTaskHeartbeat call. Activity implementation should cancel itself and report back to the service using RespondActivityTaskCanceled API call.
See Error Handling section of AWS Flow Framework Developer Guide for the AWS Flow Framework way of cancelling activities.
Sometimes activity implementation cannot support heartbeating and self cancellation. The solution is to execute another kill activity that terminates the first activity execution. For example under Unix such kill activity could emit "kill -9" command for the process that implements the first one.