{"id":44413,"date":"2015-03-23T07:00:00","date_gmt":"2015-03-23T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2015\/03\/23\/cancelioex-can-cancel-io-on-console-input-which-is-kind-of-nice\/"},"modified":"2019-03-13T12:13:58","modified_gmt":"2019-03-13T19:13:58","slug":"20150323-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20150323-00\/?p=44413","title":{"rendered":"CancelIoEx can cancel I\/O on console input, which is kind of nice"},"content":{"rendered":"<p>Today&#8217;s Little Program asks you to type something, but gives you only two seconds to do it. This is not interesting in and of itself, but it shows you how to cancel console I\/O. There is no motivation for this exercise because Little Programs come with little to no motivation. <\/p>\n<p>Okay, fine, here&#8217;s the motivation. <\/p>\n<blockquote CLASS=\"q\"><p>We have a GUI application that has a debug console. When the user exits the application, we cannot shut down cleanly because the debug console is stuck on a read from <code>stdin<\/code>. We want to unstick the thread gently. We don&#8217;t want to use <code>Generate&shy;Console&shy;Ctrl&shy;Event<\/code> with <code>CTRL_C_EVENT<\/code> because that will send the event to all processes using the same console, but we don&#8217;t want other processes to be affected. <\/p><\/blockquote>\n<p>Okay, now our Little Program. <\/p>\n<pre>\n#include &lt;windows.h&gt;\n#include &lt;stdio.h&gt; \/\/ horrors! mixing C and C++!\n\nDWORD CALLBACK ThreadProc(void *)\n{\n Sleep(2000);\n CancelIoEx(GetStdHandle(STD_INPUT_HANDLE), nullptr);\n return 0;\n}\n\nint __cdecl wmain(int, wchar_t **)\n{\n DWORD scratch;\n HANDLE h = CreateThread(nullptr, 0, ThreadProc,\n                         nullptr, 0, &amp;scratch);\n if (h) {\n  printf(\"type something\\n\");\n  char buffer[80];\n  if (fgets(buffer, 80, stdin) != nullptr) {\n   printf(\"you typed %s\", buffer);\n  } else if (feof(stdin)) {\n   printf(\"end-of-file reached\\n\");\n  } else if (ferror(stdin)) {\n   printf(\"error occurred\\n\");\n  }\n }\n return 0;\n}\n<\/pre>\n<p>If you type something within two seconds, it is reported back to you, but if you take too long, then the <code>Cancel&shy;Io&shy;Ex<\/code> cancels the console read, and you get an error back. <\/p>\n<p>If you want to continue, you&#8217;ll have to <code>clearerr(stdin)<\/code>, but if you just want to unstick the code that is performing the read (so that you can get the program to exit cleanly), then leaving <code>stdin<\/code> in an error state is probably better. <\/p>\n<p>(If you had used <code>Read&shy;File<\/code> instead of <code>fgets<\/code>, the read would have failed with error code <code>ERROR_OPERATION_ABORTED<\/code>, as documented by <code>Cancel&shy;Io&shy;Ex<\/code>.) <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Stop that input.<\/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-44413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Stop that input.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44413","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=44413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44413\/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=44413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=44413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=44413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}