{"id":173,"date":"2014-08-22T07:00:00","date_gmt":"2014-08-22T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/08\/22\/why-does-the-openthread-function-behave-differently-when-the-target-thread-belongs-to-another-process\/"},"modified":"2014-08-22T07:00:00","modified_gmt":"2014-08-22T07:00:00","slug":"why-does-the-openthread-function-behave-differently-when-the-target-thread-belongs-to-another-process","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140822-00\/?p=173","title":{"rendered":"Why does the OpenThread function behave differently when the target thread belongs to another process?"},"content":{"rendered":"<p>A customer discovered strange behavior in the <code>Open&shy;Thread<\/code> function and wondered whether it was expected.<\/p>\n<blockquote class=\"q\"><p> We use the <code>Open&shy;Thread<\/code> function to obtain a thread handle with <code>THREAD_QUE&shy;RY_LIM&shy;IT&shy;ED_IN&shy;FOR&shy;MA&shy;TION<\/code>, passing in a valid thread ID. We later pass this handle to <code>Get&shy;Exit&shy;Code&shy;Thread<\/code> to get the thread exit code. We have found that the function succeeds if the thread in question belongs to another process, provided the thread is still running (has not yet exited). On the other hand, if the thread belongs to our own process, then the call always succeeds regardless of whether the thread is running or not. Is this expected behavior? And can we assume that if <code>Open&shy;Thread<\/code> fails with <code>ERROR_INVALID_PARAMETER<\/code>, then it means that the target thread has already exited? <\/p><\/blockquote>\n<p> The <code>Open&shy;Thread<\/code> function fails if you pass it an invalid thread ID. Thread IDs go invalid when the corresponding thread object is destroyed, and thread objects are destroyed when the thread exits and there are no open handles to the thread. Once a thread object is destroyed, its thread ID becomes invalid and may be re-used by a future thread.\n Whether the thread belongs to the same process or a different process does not play a r&ocirc;le in this determination.\n My guess is that the reason the call succeeds if the target thread belongs to the same process, even if the target thread has already exited, is something much more mundane: They have a thread handle leak in their application.\n The customer never wrote back after receiving this explanation, so we&#8217;ll never know whether my guess was correct.<\/p>\n<p> <b>Bonus chatter<\/b>: If you aren&#8217;t sure whether you are passing a valid thread ID to <code>Open&shy;Thread<\/code>, then you most likely already have a bug. Since thread IDs can be reused, if you haven&#8217;t taken other steps to ensure that the thread you want still exists, then it&#8217;s possible that the thread you want has already exited, the corresponding thread object has been destroyed, and the thread ID has been reused by some other thread. Your <code>Open&shy;Thread<\/code> call will now <i>succeed<\/i>, but it will refer to some totally unrelated thread. Your program will most likely get very confused at this point. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer discovered strange behavior in the Open&shy;Thread function and wondered whether it was expected. We use the Open&shy;Thread function to obtain a thread handle with THREAD_QUE&shy;RY_LIM&shy;IT&shy;ED_IN&shy;FOR&shy;MA&shy;TION, passing in a valid thread ID. We later pass this handle to Get&shy;Exit&shy;Code&shy;Thread to get the thread exit code. We have found that the function succeeds if 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-173","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer discovered strange behavior in the Open&shy;Thread function and wondered whether it was expected. We use the Open&shy;Thread function to obtain a thread handle with THREAD_QUE&shy;RY_LIM&shy;IT&shy;ED_IN&shy;FOR&shy;MA&shy;TION, passing in a valid thread ID. We later pass this handle to Get&shy;Exit&shy;Code&shy;Thread to get the thread exit code. We have found that the function succeeds if the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/173","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=173"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/173\/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=173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}