{"id":11313,"date":"2011-03-03T07:00:00","date_gmt":"2011-03-03T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/03\/03\/if-youre-waiting-for-io-to-complete-it-helps-if-you-actually-have-an-io-to-begin-with\/"},"modified":"2011-03-03T07:00:00","modified_gmt":"2011-03-03T07:00:00","slug":"if-youre-waiting-for-io-to-complete-it-helps-if-you-actually-have-an-io-to-begin-with","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110303-00\/?p=11313","title":{"rendered":"If you&#039;re waiting for I\/O to complete, it helps if you actually have an I\/O to begin with"},"content":{"rendered":"<p>\nWe saw earlier\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/02\/03\/10124060.aspx\">\nthe importance of waiting for I\/O to complete before\nfreeing the data structures associated with that I\/O<\/a>.\nOn the other hand, before you start waiting, you have to make\nsure that you have something to wait <i>for<\/i>.\n<\/p>\n<p>\nA customer reported a hang in <code>Get&shy;Overlapped&shy;Result<\/code>\nwaiting for an I\/O to cancel, and the\nI\/O team was brought in to investigate.\nThey looked at the I\/O stack and found that the I\/O the customer\nwas waiting for was no longer active.\nThe I\/O people considered a few possibilities.\n<\/p>\n<ul>\n<li>The I\/O was active at one point, but when it completed,\n    a driver bug prevented the completion event from being signaled.\n<\/li>\n<li>The I\/O was active at one point, and the I\/O completed,\n    but the program inadvertently called <code>Reset&shy;Event<\/code>\n    on the handle, negating the <code>Set&shy;Event<\/code> performed\n    by the I\/O subsystem.\n<\/li>\n<li>The I\/O was never active in the first place.\n<\/li>\n<\/ul>\n<p>\nThese possibilities are in increasing order of likelihood\n(and, perhaps not coincidentally,\ndecreasing order of relevance to the I\/O team).\n<\/p>\n<p>\nA closer investigation of the customer&#8217;s code showed a code path\nin which the <code>Read&shy;File<\/code> call was bypassed.\nWhen the bypass code path rejoined the mainline code path,\nthe code continued its work for a while, and then if it decided\nthat it was tired of waiting for the read to complete, it\nperformed a <code>Cancel&shy;Io<\/code> followed by a\n<code>Get&shy;Overlapped&shy;Result<\/code> to\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/02\/02\/10123392.aspx\">\nwait for the cancellation to complete<\/a>.\n<\/p>\n<p>\nIf you never issue the I\/O, then a wait for the I\/O to complete\nwill wait forever,\nsince you&#8217;re waiting for something that will never happen.\n<\/p>\n<p>\nOkay, so maybe this was a dope-slap type of bug.\nBut here&#8217;s something perhaps a little less self-evident:\n<\/p>\n<pre>\n<i>\/\/ there is a flaw in this code - see discussion\n\/\/ assume operating on a FILE_FLAG_OVERLAPPED file\nif (ReadFile(h, ..., &amp;overlapped)) {\n \/\/ I\/O completed synchronously, as we learned earlier\n} else {\n \/\/ I\/O under way\n ... do stuff ...\n \/\/ okay, let's wait for that I\/O\n GetOverlappedResult(h, &amp;overlapped, &amp;dwRead, TRUE);\n ...\n}<\/i>\n<\/pre>\n<p>\nThe <code>Get&shy;Overlapped&shy;Result<\/code> call can hang here\nbecause the comment &#8220;I\/O is under way&#8221; is overly optimistic:\nThe I\/O may never even have gotten started.\nIf it never started, then it will never complete either.\nYou cannot assume that a <code>FALSE<\/code> return from\n<code>Read&shy;File<\/code> implies that the I\/O is under way.\nYou also have to check that <code>Get&shy;Last&shy;Error()<\/code>\nreturns <code>ERROR_IO_PENDING<\/code>.\nOtherwise, the I\/O failed to start, and you shouldn&#8217;t wait for it.\n<\/p>\n<pre>\n\/\/ assume operating on a FILE_FLAG_OVERLAPPED file\nif (ReadFile(h, ..., &amp;overlapped)) {\n \/\/ I\/O completed synchronously, as we learned earlier\n} else <font COLOR=\"blue\">if (GetLastError() == ERROR_IO_PENDING)<\/font> {\n \/\/ I\/O under way\n ... do stuff ...\n \/\/ okay, let's wait for that I\/O\n GetOverlappedResult(h, &amp;overlapped, &amp;dwRead, TRUE);\n ...\n<font COLOR=\"blue\">} else {\n \/\/ I\/O failed - don't wait because there's nothing to wait for!\n}<\/font>\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>We saw earlier the importance of waiting for I\/O to complete before freeing the data structures associated with that I\/O. On the other hand, before you start waiting, you have to make sure that you have something to wait for. A customer reported a hang in Get&shy;Overlapped&shy;Result waiting for an I\/O to cancel, and the [&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-11313","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>We saw earlier the importance of waiting for I\/O to complete before freeing the data structures associated with that I\/O. On the other hand, before you start waiting, you have to make sure that you have something to wait for. A customer reported a hang in Get&shy;Overlapped&shy;Result waiting for an I\/O to cancel, and the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11313","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=11313"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11313\/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=11313"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11313"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11313"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}