Service Stop Problem

  • Thread starter Thread starter Prasad
  • Start date Start date
P

Prasad

Hi,
Is it generally acceptable that the SCM says that the service has
stopped but the service has spawn a thread which is still doing the cleanup
thing which keeps the process running.
 
Not really. A service should not return from OnStop() until it has completed
cleaning up.

It should be noted that the SCM is a little smarter than just taking a
services word on if it has been stopped or not. Even if you have a thread
keeping your process alive, the SCM is likely to still kill it once the
accepted window for shutting down has elapsed.

Brendan
 
Hi,
This was your reply to my previous post wherein u asked me to create a
secondary thread which would do the cleanup thing.
Another thing is that my service is a .NET Service so is there anything
like the Win32 Service wherein we get the handler
and inform the handler about the status of the Service and extend the
time to Stop.

//Previous Post.
The Services Control Manager (SCM)
(http://msdn.microsoft.com/library/d...n-us/dllproc/base/service_control_manager.asp)
has a default of 30 seconds for the amount of time it will wait for a
service
to complete after OnStart or OnStop are called, if this limit is exceeded,
it
will forcibly terminate the process as it sounds like you have discovered.

One way around this (to quote from
http://msdn.microsoft.com/library/d...roc/base/service_control_handler_function.asp)
is:

The control handler must return within 30 seconds, or the SCM returns an
error. If a service must do lengthy processing when the service is executing
the control handler, it should create a secondary thread to perform the
lengthy processing, and then return from the control handler. This prevents
the service from tying up the control dispatcher. For example, when handling
the stop request for a service that takes a long time, create another thread
to handle the stop process. The control handler should simply call
SetServiceStatus with the SERVICE_STOP_PENDING message and return.

Brendan


Prasad said:
Hi,
I am writing a service which takes a long time to stop after the
OnStop
call is given by the Services Snap-in. The problem is I cannot cut down on
the time that it takes to Stop. The Service snap-in gives me the error
saying that the service did not respond to the Stop call in a timely
fashion. So is there any method by which I can get around this problem.

Thanks
Prasad

//Current Post.
 
The only way I know of to prevent the SCM from terminating your process is
to have it host another Service - a process can host more than one.
Obviously you end up with a lot more infrastructure (installation) and
logistics (two Services) that you have to deal with, but the other Service
doesn't actually have to do anything useful. However you might be better off
launching some other process to handle whatever makes the shutdown slow.
 
It should be avoided, really confusing to operations people. However, there
doesn't seem to be a [good] work around for a dotnet service. The
ServiceController doesn't expose SetServiceStatus()... so I can't see how you
would set SERVICE_STATUS dwWaitHint, dwCheckPoint (estimated time/keep alive
respectively).

Someone mentioned DependantServices... you could kludge it IF you know some
absolute maximum time to Stop. Each DependantService gets 30 seconds to Stop.
Soooo, if you had a bunch of DummyServices... and the last one was your real
service... you might be able to get the time you need.

ServiceController.Stop() looks like this...

Anyone knows a good way to coordinate Stop time (SetServiceStatus) please
post it ;)

for (int num1 = 0; num1 < this.DependentServices.Length; num1++)
{
if (this.DependentServices[num1].Status !=
ServiceControllerStatus.Stopped)
{
this.DependentServices[num1].Stop();

this.DependentServices[num1].WaitForStatus(ServiceControllerStatus.Stopped,
new TimeSpan(0, 0, 30));
}
}
NativeMethods.SERVICE_STATUS service_status1 = new
NativeMethods.SERVICE_STATUS();
if (!UnsafeNativeMethods.ControlService(ptr1, 1,
&service_status1)) // SERVICE_CONTROL_STOP
{
Exception exception1 =
ServiceController.CreateSafeWin32Exception();
object[] objArray1 = new object[2] { this.ServiceName,
this.MachineName } ;
throw new
InvalidOperationException(Res.GetString("StopService", objArray1),
exception1);
}
 
Win32 has SetServiceStatus() to coordinate estimated stop time and that you
are making progress... we just don't have access to it.

/jhd
 
Back
Top