Gracefully handling shutdown of a Windows service

Maritim

Assume that you have a multi-threaded Windows service which performs lots of different operations which takes a fair share of time, e.g. extracting data from different data stores, parsing said data, posting it to an external server etc. Operations may be performed in different layers, e.g. application layer, repository layer or service layer.

At some point in the lifespan of this Windows service you may wish to shut it down or restart it by way of services.msc, however if you can't stop all operations and terminate all threads in the Windows service within the timespan that services.msc expects to be done with the stop procedure, it will hang and you will have to kill it from Task Manager.

Because of the issue mentioned above, my question is as follows: How would you implement a fail-safe way of handling shutdown of your Windows service? I have a volatile boolean that acts as a shutdown signal, enabled by OnStop() in my service base class, and should gracefully stop my main loop, but that isn't worth anything if there is an operation in some other layer which is taking it's time doing whatever that operation is up to.

How should this be handled? I'm currently at a loss and need some creative input.

Maritim

After more research and some brainstorming I came to realise that the problems I've been experiencing were being caused by a very common design flaw regarding threads in Windows services.

The design flaw

Imagine you have a thread which does all your work. Your work consists of tasks that should be run again and again indefinitely. This is quite often implemented as follows:

volatile bool keepRunning = true;
Thread workerThread;

protected override void OnStart(string[] args)
{
    workerThread = new Thread(() =>
    {
        while(keepRunning)
        {
            DoWork();
            Thread.Sleep(10 * 60 * 1000); // Sleep for ten minutes
        }
    });
    workerThread.Start();
}

protected override void OnStop()
{
    keepRunning = false;
    workerThread.Join();
    // Ended gracefully
}

This is the very common design flaw I mentioned. The problem is that while this will compile and run as expected, you will eventually experience that your Windows service won't respond to commands from the service console in Windows. This is because your call to Thread.Sleep() blocks the thread, causing your service to become unresponsive. You will only experience this error if the thread blocks for longer than the timeout configured by Windows in HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout, because of this registry value this implementation may work for you if your thread is configured to sleep for a very short period of time and does it's work in an acceptable period of time.

The alternative

Instead of using Thread.Sleep() I decided to go for ManualResetEvent and System.Threading.Timer instead. The implementation looks something like this:

OnStart:

this._workerTimer = new Timer(new TimerCallback(this._worker.DoWork));
this._workerTimer.Change(0, Timeout.Infinite); // This tells the timer to perform the callback right now

Callback:

if (MyServiceBase.ShutdownEvent.WaitOne(0)) // My static ManualResetEvent
    return; // Exit callback

// Perform lots of work here
ThisMethodDoesAnEnormousAmountOfWork();

(stateInfo as Timer).Change(_waitForSeconds * 1000, Timeout.Infinite); // This tells the timer to execute the callback after a specified period of time. This is the amount of time that was previously passed to Thread.Sleep()

OnStop:

MyServiceBase.ShutdownEvent.Set(); // This signals the callback to never ever perform any work again
this._workerTimer.Dispose(); // Dispose of the timer so that the callback is never ever called again

The conclusion

By implementing System.Threading.Timer and ManualResetEvent you will avoid your service becoming unresponsive to service console commands as a result of Thread.Sleep() blocking.

PS! You may not be out of the woods just yet!

However, I believe there are cases in which a callback is assigned so much work by the programmer that the service may become unresponsive to service console commands during workload execution. If that happens you may wish to look at alternative solutions, like checking your ManualResetEvent deeper in your code, or perhaps implementing CancellationTokenSource.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Handling child process shutdown gracefully

From Dev

Is it possible to gracefully shutdown a Self-Hosted ServiceStack service?

From Dev

Is it possible to gracefully shutdown a Self-Hosted ServiceStack service?

From Dev

stop apache gracefully at shutdown

From Dev

How does a windows service behaves on Windows shutdown?

From Dev

How do you gracefully shutdown a Java service from a Bash shell script?

From Dev

How to gracefully shutdown embeded jetty

From Dev

How to gracefully shutdown a thread in C

From Dev

Accessing Windows Service Startup or Shutdown Progress Values

From Dev

Exception handling - gracefully exit

From Dev

How to stop windows service created by install4j gracefully?

From Dev

How do I gracefully handle this exception in a background thread in a Windows service?

From Dev

How to stop windows service created by install4j gracefully?

From Dev

Windows Service Exception Handling and Timers

From Dev

How to catch SERVICE_CONTROL_SHUTDOWN code in Windows Service Program

From Dev

windows service using shutdown event cant stop the service

From Dev

Grails and Quartz on Tomcat: how to gracefully shutdown

From Dev

Grails and Quartz on Tomcat: how to gracefully shutdown

From Dev

Gracefully shut down QEMU/KVM on host shutdown

From Dev

Shutdown a java app (multiple threads) gracefully

From Dev

Handling AppDomain.CurrentDomain.UnhandledException in windows service

From Dev

Handling AppDomain.CurrentDomain.UnhandledException in windows service

From Dev

Date business handling Windows Service on C#

From Dev

How to ensure a small UnitOfWork job is completed on a windows service Stop or Shutdown

From Dev

c++ service doesn't start after windows shutdown and then boot

From Dev

Shutdown Windows without Shutdown banner

From Dev

Importing Python libraries and gracefully handling if they are not availalble

From Dev

Handling SSL_shutdown correctly

From Dev

How to shutdown a service correctly

Related Related

  1. 1

    Handling child process shutdown gracefully

  2. 2

    Is it possible to gracefully shutdown a Self-Hosted ServiceStack service?

  3. 3

    Is it possible to gracefully shutdown a Self-Hosted ServiceStack service?

  4. 4

    stop apache gracefully at shutdown

  5. 5

    How does a windows service behaves on Windows shutdown?

  6. 6

    How do you gracefully shutdown a Java service from a Bash shell script?

  7. 7

    How to gracefully shutdown embeded jetty

  8. 8

    How to gracefully shutdown a thread in C

  9. 9

    Accessing Windows Service Startup or Shutdown Progress Values

  10. 10

    Exception handling - gracefully exit

  11. 11

    How to stop windows service created by install4j gracefully?

  12. 12

    How do I gracefully handle this exception in a background thread in a Windows service?

  13. 13

    How to stop windows service created by install4j gracefully?

  14. 14

    Windows Service Exception Handling and Timers

  15. 15

    How to catch SERVICE_CONTROL_SHUTDOWN code in Windows Service Program

  16. 16

    windows service using shutdown event cant stop the service

  17. 17

    Grails and Quartz on Tomcat: how to gracefully shutdown

  18. 18

    Grails and Quartz on Tomcat: how to gracefully shutdown

  19. 19

    Gracefully shut down QEMU/KVM on host shutdown

  20. 20

    Shutdown a java app (multiple threads) gracefully

  21. 21

    Handling AppDomain.CurrentDomain.UnhandledException in windows service

  22. 22

    Handling AppDomain.CurrentDomain.UnhandledException in windows service

  23. 23

    Date business handling Windows Service on C#

  24. 24

    How to ensure a small UnitOfWork job is completed on a windows service Stop or Shutdown

  25. 25

    c++ service doesn't start after windows shutdown and then boot

  26. 26

    Shutdown Windows without Shutdown banner

  27. 27

    Importing Python libraries and gracefully handling if they are not availalble

  28. 28

    Handling SSL_shutdown correctly

  29. 29

    How to shutdown a service correctly

HotTag

Archive