{"id":7322,"date":"2019-05-14T06:58:17","date_gmt":"2019-05-14T13:58:17","guid":{"rendered":"https:\/\/www.coretechnologies.com\/blog\/?p=7322"},"modified":"2022-04-19T22:07:49","modified_gmt":"2022-04-20T05:07:49","slug":"increase-shutdown-time","status":"publish","type":"post","link":"https:\/\/www.coretechnologies.com\/blog\/windows-services\/increase-shutdown-time\/","title":{"rendered":"Q&#038;A: How Do I Give my Windows Service More Time to Stop During Shutdown?"},"content":{"rendered":"<div align=\"center\"><img loading=\"lazy\" decoding=\"async\" class=\"no-lazy-load\" src=\"\/blog\/images\/qa-increase-windows-service-shutdown-timeout.webp\" title=\"Q&#038;A - Increase Service Timeout\" alt=\"Q&#038;A - Increase Service Timeout\" border=\"0\" width=\"380\" height=\"160\" \/><\/div>\n<div class=\"blog-qa-question-box\">\n<img loading=\"lazy\" decoding=\"async\" class=\"no-lazy-load\" src=\"https:\/\/cdn.coretechnologies.com\/images\/quotes-transparent-21x21.webp\" width=\"21\" height=\"21\" \/>&nbsp;&nbsp;One of our file ingestion services can take a while to finish all pending database updates and exit cleanly. Sometimes when we reboot the server, Windows doesn&#8217;t wait for the service to finish, and we end up with database corruption, which is a huge pain.<\/p>\n<p>How do I get Windows to <b>wait until my service is done<\/b> and not kill it while it&#8217;s still working?<\/p>\n<p align=\"right\">&mdash; Jeff<\/p>\n<\/div>\n<p>Hi Jeff, sorry to hear of the database corruption!<\/p>\n<p>For obvious reasons, Windows tries to shut itself down as quickly as possible. The goal is to complete the process in <b>20 seconds or less<\/b>.<\/p>\n<p>Applications and services that don&#8217;t respond within that time frame are classified as hung and are promptly terminated. As you have seen, this can lead to undesirable results.<\/p>\n<p>Clearly this bias towards a quick shutdown makes sense for a desktop computer because a person is likely waiting patiently at the keyboard and mouse. However, it not ideal for servers running important background processes. In the server scenario, where interactive user experience is less of an issue, <b>a safe shutdown should take precedence over a speedy one!<\/b><\/p>\n<p>Fortunately there are a couple of ways to swing the balance of power to your Windows Service:<\/p>\n<h2 class=\"blog-caption-numbered\">1. Extend the &#8220;Shutdown Timeout&#8221; for all Windows Services<\/h2>\n<p><a name=\"service-shutdown-procedure\"><\/a>As far as services are concerned, Windows follows this procedure when shutting down:<\/p>\n<ol>\n<li>\n<p>Windows informs each service that it should shut down<\/p>\n<\/li>\n<li>Windows waits until either:\n<ul>\n<li>all services have stopped, or<\/li>\n<li>a fixed period has elapsed.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Windows forcibly terminates any services still running<\/p>\n<\/li>\n<\/ol>\n<p>By default, that &#8220;fixed period&#8221; is only 5 seconds &mdash; insufficient time for your busy service to wind down gracefully.<\/p>\n<p>Fortunately we can extend that period by modifying this registry value:<\/p>\n<blockquote><p><b>HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\WaitToKillServiceTimeout<\/b><\/p><\/blockquote>\n<p>How long does your service need to exit gracefully? Will 60 seconds be enough?<\/p>\n<p>To change the timeout:<\/p>\n<ol>\n<li>\n<p>Start the <a href=\"https:\/\/support.microsoft.com\/en-us\/help\/4027573\/windows-10-open-registry-editor\" target=\"_blank\" rel=\"noopener noreferrer\">registry editor<\/a> (&#8220;regedit&#8221;)<\/p>\n<\/li>\n<li>\n<p>In the tree on the left, navigate to:<\/p>\n<blockquote><p><b>HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control<\/b><\/p><\/blockquote>\n<\/li>\n<li>\n<p>In the right panel, find the <b>WaitToKillServiceTimeout<\/b> value. If you don&#8217;t see it, create it by:<\/p>\n<ol type=\"a\">\n<li>\n<p>Selecting <b>Control<\/b> on the left<\/p>\n<\/li>\n<li>\n<p>Choosing <b>Edit &gt; New &gt; String Value<\/b> (not DWORD) from the menu<\/p>\n<\/li>\n<li>\n<p>Naming the new value <b>WaitToKillServiceTimeout<\/b>.<\/p>\n<\/li>\n<\/ol>\n<div align=\"center\"><a href=\"\/blog\/images\/waittokillservicetimeout-registry-value.png\" class=\"zoomPopup\" title=\"WaitToKillServiceTimeout registry value\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"image-padding\" src=\"\/blog\/images\/waittokillservicetimeout-registry-value.png\" title=\"WaitToKillServiceTimeout registry value (click to enlarge)\" alt=\"WaitToKillServiceTimeout registry value\" border=\"0\" width=\"520\"><\/a><\/div>\n<\/li>\n<li>\n<p>Double-click the WaitToKillServiceTimeout entry to bring up the <b>Edit String<\/b> window. Enter 60000 in the <b>Value data<\/b> field (it&#8217;s in milliseconds) and click <b>OK<\/b> to save your change.<\/p>\n<div align=\"center\"><a href=\"\/blog\/images\/change-waittokillservicetimeout-value.png\" class=\"zoomPopup\" title=\"Change WaitToKillServiceTimeout\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"image-padding\" src=\"\/blog\/images\/change-waittokillservicetimeout-value.png\" title=\"Change WaitToKillServiceTimeout (click to enlarge)\" alt=\"Change WaitToKillServiceTimeout\" border=\"0\"><\/a><\/div>\n<\/li>\n<li>\n<p>Reboot your computer. You don&#8217;t have to do that right now, but the new timeout setting <b>will not take effect until Windows restarts<\/b>.<\/p>\n<\/li>\n<\/ol>\n<p>Note that this modification will not make Windows wait indefinitely for your service to finish. If your service takes longer than 60 seconds, it will still be terminated. Be sure to choose a timeout value that is long enough to cover your scenario, but not too long to make shutdown intolerable.<\/p>\n<h2 class=\"blog-caption-numbered\">2. Update your Windows Service to accept Preshutdown Notifications<\/h2>\n<p>Changing the WaitToKillServiceTimeout setting is a quick fix but the delay you specify will apply to <b>all services<\/b>. If another, non-critical service is hung, Windows will wait the full duration before terminating it.<\/p>\n<p>To make sure that Windows waits for your specific service, you should update the code to accept <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/services\/service-control-handler-function\" target=\"_blank\" rel=\"noopener noreferrer\">preshutdown notifications<\/a>. <\/p>\n<p>Specifically, your service must:<\/p>\n<ol>\n<li>\n<p>Call the <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/Winsvc\/nf-winsvc-setservicestatus\" target=\"_blank\" rel=\"noopener noreferrer\">SetServiceStatus<\/a> function, passing the SERVICE_ACCEPT_PRESHUTDOWN flag in the <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/winsvc\/ns-winsvc-service_status\" target=\"_blank\" rel=\"noopener noreferrer\">SERVICE_STATUS<\/a> structure;<\/p>\n<\/li>\n<li>\n<p>Clean up and exit when it receives the SERVICE_CONTROL_PRESHUTDOWN notification.<\/p>\n<\/li>\n<\/ol>\n<p><a href=\"http:\/\/www.sivachandran.in\/2012\/03\/handling-pre-shutdown-notification-in-c.html\" target=\"_blank\" rel=\"noopener noreferrer\">This article<\/a> reviews the code to be added in C# projects.<\/p>\n<h3 class=\"larger\"><b>How preshutdown works<\/b><\/h3>\n<p>The preshutdown process was introduced in Windows Vista (circa 2007). As the name suggests, it runs before the regular shutdown process. Its purpose is to give mission-critical services an early start on exiting, ahead of less important modules.<\/p>\n<p>The preshutdown process looks like this:<\/p>\n<ol>\n<li>\n<p>Windows notifies all services that have registered for preshutdown notifications to exit<\/p>\n<\/li>\n<li>For each of those services, Windows waits until either:\n<ul>\n<li>the service has stopped, or<\/li>\n<li>a fixed period has elapsed.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Windows proceeds with the regular shutdown procedure (<a href=\"#service-shutdown-procedure\">see above<\/a>)<\/p>\n<\/li>\n<\/ol>\n<p>By default, that fixed period is 180 seconds (3 minutes) &mdash; more than enough time for most Windows Services to tidy up and exit gracefully.<\/p>\n<p>But what if you need more than three minutes? Fortunately Microsoft has provided a solution there as well&#8230;<\/p>\n<h3 class=\"larger\"><b>How to extend the preshutdown timeout beyond 3 minutes<\/b><\/h3>\n<p>With a simple code change, a preshutdown service can instruct Windows to wait more than the default 3 minutes for the service to end in the preshutdown phase.<\/p>\n<p>You must add code to call the <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/winsvc\/nf-winsvc-changeserviceconfig2a\" target=\"_blank\" rel=\"noopener noreferrer\">ChangeServiceConfig2<\/a> function with the SERVICE_CONFIG_PRESHUTDOWN_INFO level, and the timeout value in the <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/winsvc\/ns-winsvc-service_preshutdown_info\" target=\"_blank\" rel=\"noopener noreferrer\">SERVICE_PRESHUTDOWN_INFO<\/a> structure set to an appropriate value.<\/p>\n<p>Here is what the addition looks like in C++ (error checking omitted for brevity):<\/p>\n<div class=\"code-box\">\n<pre>\r\n   SC_HANDLE hService =\tOpenService(...);\r\n   ...\r\n   SERVICE_PRESHUTDOWN_INFO info;\r\n   info.dwPreshutdownTimeout = 5 * 60 * 1000; \/\/ 5 minutes\r\n   ChangeServiceConfig2(hService, SERVICE_CONFIG_PRESHUTDOWN_INFO, &info);\r\n<\/pre>\n<\/div>\n<p>The new code is best called once when you install\/setup your service, but it can be invoked during normal operation as well. Whichever works better in your situation.<\/p>\n<p style=\"margin-top:40px;\">\nHopefully one of these two solutions will delay shutdown long enough to eliminate the database corruption. Please try them, and be sure to <a href=\"\/support\/\">get in touch<\/a> if you have any questions!<\/p>\n<!-- relpost-thumb-wrapper --><div class=\"relpost-thumb-wrapper\"><!-- filter-class --><div class=\"relpost-thumb-container\"><style>.relpost-block-single-image, .relpost-post-image { margin-bottom: 10px; }<\/style><h3>You may also like...<\/h3><div style=\"clear: both\"><\/div><div style=\"clear: both\"><\/div><!-- relpost-block-container --><div class=\"relpost-block-container relpost-block-column-layout\" style=\"--relposth-columns: 3;--relposth-columns_t: 2; --relposth-columns_m: 2\"><a href=\"https:\/\/www.coretechnologies.com\/blog\/alwaysup\/multiple-alpha-servers\/\"class=\"relpost-block-single\" ><div class=\"relpost-custom-block-single\"><img decoding=\"async\" loading=\"lazy\" class=\"relpost-block-single-image\" alt=\"Q &amp; A: How do I Prevent Multiple Alpha Application Servers from Running?\"  src=\"https:\/\/www.coretechnologies.com\/blog\/wp-content\/uploads\/qa-150x150.png\" style=\"aspect-ratio:1\/1\" style=\"aspect-ratio:1\/1\"><\/img><div class=\"relpost-block-single-text\"  style=\"height: 75px;font-family: Arial;  font-size: 12px;  color: #333333;\"><h2 class=\"relpost_card_title\">Q &amp; A: How do I Prevent Multiple Alpha Application Servers from Running?<\/h2><\/div><\/div><\/a><a href=\"https:\/\/www.coretechnologies.com\/blog\/alwaysup\/dropbox-smart-sync-problem\/\"class=\"relpost-block-single\" ><div class=\"relpost-custom-block-single\"><img decoding=\"async\" loading=\"lazy\" class=\"relpost-block-single-image\" alt=\"Q&amp;A: Why can&#039;t I open my Dropbox files even though Smart Sync is off?\"  src=\"https:\/\/www.coretechnologies.com\/blog\/wp-content\/uploads\/dropbox-documents-150x150-1.png\" style=\"aspect-ratio:1\/1\" style=\"aspect-ratio:1\/1\"><\/img><div class=\"relpost-block-single-text\"  style=\"height: 75px;font-family: Arial;  font-size: 12px;  color: #333333;\"><h2 class=\"relpost_card_title\">Q&amp;A: Why can&#039;t I open my Dropbox files even though Smart Sync is off?<\/h2><\/div><\/div><\/a><a href=\"https:\/\/www.coretechnologies.com\/blog\/windows\/windows-server-2019-preview\/\"class=\"relpost-block-single\" ><div class=\"relpost-custom-block-single\"><img decoding=\"async\" loading=\"lazy\" class=\"relpost-block-single-image\" alt=\"Windows Server 2019\"  src=\"https:\/\/www.coretechnologies.com\/blog\/wp-content\/uploads\/windows-server-2019-150x1501.png\" style=\"aspect-ratio:1\/1\" style=\"aspect-ratio:1\/1\"><\/img><div class=\"relpost-block-single-text\"  style=\"height: 75px;font-family: Arial;  font-size: 12px;  color: #333333;\"><h2 class=\"relpost_card_title\">An Early Look at Windows Server 2019<\/h2><\/div><\/div><\/a><\/div><!-- close relpost-block-container --><div style=\"clear: both\"><\/div><\/div><!-- close filter class --><\/div><!-- close relpost-thumb-wrapper -->","protected":false},"excerpt":{"rendered":"<p>&nbsp;&nbsp;One of our file ingestion services can take a while to finish all pending database updates and exit cleanly. Sometimes when we reboot the server, Windows doesn&#8217;t wait for the service to finish, and we end up with database corruption, &hellip; <a href=\"https:\/\/www.coretechnologies.com\/blog\/windows-services\/increase-shutdown-time\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":7537,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18],"tags":[51,127,146,149,154,182,196],"class_list":["post-7322","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-windows-services","tag-change-service-config2","tag-qa","tag-service-preshutdown","tag-service-shutdown","tag-set-service-status","tag-wait-to-kill-service-timeout","tag-windows-services-2"],"_links":{"self":[{"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/posts\/7322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/comments?post=7322"}],"version-history":[{"count":2,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/posts\/7322\/revisions"}],"predecessor-version":[{"id":11242,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/posts\/7322\/revisions\/11242"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/media\/7537"}],"wp:attachment":[{"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/media?parent=7322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/categories?post=7322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.coretechnologies.com\/blog\/wp-json\/wp\/v2\/tags?post=7322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}