{"id":97256,"date":"2017-10-20T07:00:00","date_gmt":"2017-10-20T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=97256"},"modified":"2019-03-13T01:19:12","modified_gmt":"2019-03-13T08:19:12","slug":"20171020-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20171020-00\/?p=97256","title":{"rendered":"On the gradual improvements in how the system deals with the failure to initialize a critical section"},"content":{"rendered":"<p>The <a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/ms683472(v=vs.85).aspx\">documentation for the <code>Initialize&shy;Critical&shy;Section<\/code> function<\/a> says <\/p>\n<blockquote CLASS=\"q\">\n<p STYLE=\"font-size: 120%\">Return value <\/p>\n<p>This function does not return a value. <\/p>\n<p><b>Windows Server 2003 and Windows XP<\/b>: In low memory situations, <b>Initialize&shy;Critical&shy;Section<\/b> can raise a <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception. This exception was eliminated starting with Windows Vista. <\/p>\n<\/blockquote>\n<p>In earlier versions of Windows, the <code>Initialize&shy;Critical&shy;Section<\/code> function could fail in low memory conditions, in which case it raised a <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception. <\/p>\n<p>Wait, let&#8217;s go back even further. <\/p>\n<p>In very old versions of Windows, the <code>Initialize&shy;Critical&shy;Section<\/code> function could fail in low memory conditions, in which case it raised a <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception. However, the code wasn&#8217;t particularly careful about exactly when it raised the exception, and it turns out that it didn&#8217;t bother to completely unwind the partial-initialization-so-far before raising the exception. This means that if a program tried to recover from a failed <code>Initialize&shy;Critical&shy;Section<\/code> by catching the <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception, it still experienced a memory leak. <\/p>\n<p>Yes, it&#8217;s rather ironic that if the kernel couldn&#8217;t initialize the critical section due to low resources, it leaked memory, which made the low resource situation <i>even worse<\/i>. <\/p>\n<p>There was a similar sad story with <code>Enter&shy;Critical&shy;Section<\/code> and even <code>Leave&shy;Critical&shy;Section<\/code>: Under low resource conditions, those functions could fail and raise a <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception. Those are even worse because by the time you get the exception, it&#8217;s probably too late to back out of whatever you were doing. I mean, maybe if you&#8217;re really clever, you can recover from a failed <code>Enter&shy;Critical&shy;Section<\/code> by abandoning the operation (and undoing all the work done so far), but I can&#8217;t think of any case where a program could do anything reasonable if <code>Leave&shy;Critical&shy;Section<\/code> fails. <\/p>\n<p>And <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/#comment-1150233\">as Michael Grier noted<\/a>, if <code>Leave&shy;Critical&shy;Section<\/code> raised an exception, not only wasn&#8217;t there anything you could reasonably do about it, but it also left the critical section in a corrupted state! <\/p>\n<p>The only thing you can do is to just crash the process before things get any worse. <\/p>\n<p>I think it was in Windows XP that the kernel folks fixed the code so that it cleaned up the partially-initialized critical section before raising the <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception, so that a program could safely catch the exception and not leak memory. I believe they also fixed it so that the <code>Enter&shy;Critical&shy;Section<\/code> and <code>Leave&shy;Critical&shy;Section<\/code> functions would not raise exceptions. If called properly, then they always succeeded. So at least those weird cases of &#8220;raising an exception and leaving the critical section fatally corrupted&#8221; went away. <\/p>\n<p>And then in Windows Vista, the kernel folks decided to get rid of the problem once and for all and remove all the failure cases from all the critical section functions. The <code>Initialize&shy;Critical&shy;Section<\/code> and <code>Initialize&shy;Critical&shy;Section&shy;And&shy;Spin&shy;Count<\/code> functions always succeeded. The <code>Enter&shy;Critical&shy;Section<\/code> and <code>Leave&shy;Critical&shy;Section<\/code> functions would not raise exceptions when used properly. <\/p>\n<p>So for over a decade now, the <code>Initialize&shy;Critical&shy;Section<\/code> and <code>Initialize&shy;Critical&shy;Section&shy;And&shy;Spin&shy;Count<\/code> functions never fail. This means that (assuming they are called properly), <code>Initialize&shy;Critical&shy;Section<\/code> never raises a <code>STATUS_<\/code><code>NO_<\/code><code>MEMORY<\/code> exception. The <code>Initialize&shy;Critical&shy;Section&shy;And&shy;Spin&shy;Count<\/code> function a return value that says whether it succeeded, but it always succeeds and returns a nonzero value. The return value is now superfluous. <\/p>\n<p><b>Bonus chatter<\/b>: The <a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/ms683476(v=vs.85).aspx\">documentation for the <code>Initialize&shy;Critical&shy;Section&shy;And&shy;Spin&shy;Count<\/code> function<\/a> says <\/p>\n<blockquote CLASS=\"q\">\n<p STYLE=\"font-size: 120%\">Return value <\/p>\n<p>This function always returns a nonzero value. <\/p>\n<p><b>Windows Server 2003 and Windows XP<\/b>: If the function succeeds, the return value is nonzero. If the function fails, the return value is zero (0). To get extended error information, call <b>Get&shy;Last&shy;Error<\/b>. This behavior was changed starting with Windows Vista. <\/p>\n<\/blockquote>\n<p>I&#8217;m told that some people come away from the documentation still worried about the possibility that the <code>Initialize&shy;Critical&shy;Section&shy;And&shy;Spin&shy;Count<\/code> might fail on Windows Vista and later. They see that on Windows Server 2003 and Windows XP, the function tells you whether or not it succeeded, but on Windows Vista it always reports success. &#8220;That means that if the function fails, Windows Vista will lie to me and report success even though it failed!&#8221; No, that&#8217;s not what it&#8217;s saying. It&#8217;s saying that starting in Windows Vista, the function <i>never fails<\/i>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gradually improve the situation until the problem vanishes completely.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-97256","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Gradually improve the situation until the problem vanishes completely.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97256","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=97256"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97256\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=97256"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=97256"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=97256"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}