{"id":11153,"date":"2011-03-23T07:00:00","date_gmt":"2011-03-23T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/03\/23\/function-requirements-are-cumulative-if-you-fail-to-meet-any-of-them-then-all-bets-are-off\/"},"modified":"2011-03-23T07:00:00","modified_gmt":"2011-03-23T07:00:00","slug":"function-requirements-are-cumulative-if-you-fail-to-meet-any-of-them-then-all-bets-are-off","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110323-00\/?p=11153","title":{"rendered":"Function requirements are cumulative: If you fail to meet any of them, then all bets are off"},"content":{"rendered":"<p>A customer was having problems with the <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> function:<\/p>\n<blockquote class=\"q\"><p>  We are looking for a clarification of the behavior of <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code>. We have a thread that waits on two handles (call them <code>Handle1<\/code> and <code>Handle2<\/code>) with  <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code>, <code>bWaitAll = FALSE<\/code>. Under certain conditions, we signal <code>Handle1<\/code> and close <code>Handle2<\/code> from another thread while the wait is in progress. This results in <code>WAIT_FAILED<\/code> being returned from the wait call. MSDN is not clear on what the expected behavior is here. On the one hand, it says <\/p>\n<ol type=\"A\">\n<li>When <code>bWait<\/code> is <code>FALSE<\/code>,     this function checks the handles in the array in order     starting with index 0,     until one of the objects is signaled.     If multiple objects become signaled,     the function returns the index of the first handle in the array     whose object was signaled. <\/li>\n<\/ol>\n<p> This description implies that the wait should never fail, because the function should have noticed that <code>Handle1<\/code> is signaled before it got around to noticing that <code>Handle2<\/code> was invalid. <\/p>\n<p> On the other hand, the documentation also says <\/p>\n<ol type=\"A\">\n<li value=\"2\">If one of these handle is closed while the wait     is still pending, the function&#8217;s behavior is undefined. <\/li>\n<\/ol>\n<p> What behavior is guaranteed here? <\/p>\n<\/blockquote>\n<p> Once you violate a constraint (in this case, the constraint that the handles remain valid for the duration of the wait operation), you have failed to meet the prerequisites and the behavior is undefined. You can&#8217;t say, &#8220;Well, sure you say I can&#8217;t do&nbsp;X, but if you follow exactly the steps given in this description of how signaled objects are selected, then the function wouldn&#8217;t even have noticed&nbsp;X before coming to a decision, so the fact that I broke one of the rules is irrelevant!&#8221;\n The description of the behavior of the <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> function when <code>bWait<\/code> is <code>FALSE<\/code> is not an implementation specification. It&#8217;s a description of how to interpret the behavior of the function. The algorithmic way the function behavior is described is to assist in understanding the behavior; it doesn&#8217;t mean that the function actually follows the algorithm step-by-step. (In reality, there is no polling loop, as the algorithmic description implies. All the handles are waited on simultaneously. It&#8217;s like Lebesgue integration: You integrate over the entire domain at once.)\n An algorithm-free description of the behavior when <code>bWait<\/code> is false might go like this:<\/p>\n<ol type=\"A\">\n<li>When <code>bWait<\/code> is <code>FALSE<\/code>,     the function does not return until one of the handles     in the array becomes signaled.     The return value is the smallest index corresponding     to a signaled handle. <\/li>\n<\/ol>\n<p> This description is purely declarative but gives you no mental model.\n It&#8217;s like saying that &#8220;Water seeks its own level.&#8221; Water doesn&#8217;t have a will that compels it to behave in a certain way, but describing the behavior in that way makes reasoning about water easier.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer was having problems with the Wait&shy;For&shy;Multiple&shy;Objects function: We are looking for a clarification of the behavior of Wait&shy;For&shy;Multiple&shy;Objects. We have a thread that waits on two handles (call them Handle1 and Handle2) with Wait&shy;For&shy;Multiple&shy;Objects, bWaitAll = FALSE. Under certain conditions, we signal Handle1 and close Handle2 from another thread while the wait is [&hellip;]<\/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-11153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer was having problems with the Wait&shy;For&shy;Multiple&shy;Objects function: We are looking for a clarification of the behavior of Wait&shy;For&shy;Multiple&shy;Objects. We have a thread that waits on two handles (call them Handle1 and Handle2) with Wait&shy;For&shy;Multiple&shy;Objects, bWaitAll = FALSE. Under certain conditions, we signal Handle1 and close Handle2 from another thread while the wait is [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11153","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=11153"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11153\/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=11153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}