{"id":17733,"date":"2009-06-26T10:00:00","date_gmt":"2009-06-26T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/06\/26\/the-thread-that-gets-the-dll_process_detach-notification-is-not-necessarily-the-one-that-got-the-dll_process_attach-notification\/"},"modified":"2009-06-26T10:00:00","modified_gmt":"2009-06-26T10:00:00","slug":"the-thread-that-gets-the-dll_process_detach-notification-is-not-necessarily-the-one-that-got-the-dll_process_attach-notification","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090626-00\/?p=17733","title":{"rendered":"The thread that gets the DLL_PROCESS_DETACH notification is not necessarily the one that got the DLL_PROCESS_ATTACH notification"},"content":{"rendered":"<p>The thread that gets the <code>DLL_PROCESS_DETACH<\/code> notification is not necessarily the one that got the <code>DLL_PROCESS_ATTACH<\/code> notification. This is obvious if you think about it, because the thread that got the <code>DLL_PROCESS_ATTACH<\/code> notification might not even exist any longer when the DLL is unloaded. How can something that doesn&#8217;t exist send a notification?<\/p>\n<p> Even so, many people fail to realize this. You can&#8217;t do anything with thread affinity in your <code>DLL_PROCESS_ATTACH<\/code> or <code>DLL_PROCESS_DETACH<\/code> handler since you have no guarantee about which thread will be called upon to handle these process notifications. Of course, you&#8217;re not supposed to be doing anything particularly interesting in your <code>DLL_PROCESS_ATTACH<\/code> handler anyway, but things with thread affinity are doubly bad. <\/p>\n<p> The classic example of this, which I&#8217;m told the Developer Support team run into with alarming frequency, is a DLL that creates a window in its <code>DLL_PROCESS_ATTACH<\/code> handler and destroys it in its <code>DLL_PROCESS_DETACH<\/code> handler. Now, creating a window in <code>DllMain<\/code> is already a horrifically bad idea since arbitrary code can run during the creation of a window (for example, there may be a global hook), but the lack of a thread guarantee makes it downright insane. The DLL calls <code>DestroyWindow<\/code> in its <code>DLL_PROCESS_DETACH<\/code> handler, but since that notification comes in on a thread different from the one that received the <code>DLL_PROCESS_ATTACH<\/code> notification, the attempt to destroy the window fails since you must call <code>DestroyWindow<\/code> from the same thread that created it. <\/p>\n<p> Result: The DLL&#8217;s attempt to destroy its window fails, a message comes in, and the process crashes since the window procedure no longer exists. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The thread that gets the DLL_PROCESS_DETACH notification is not necessarily the one that got the DLL_PROCESS_ATTACH notification. This is obvious if you think about it, because the thread that got the DLL_PROCESS_ATTACH notification might not even exist any longer when the DLL is unloaded. How can something that doesn&#8217;t exist send a notification? Even so, [&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-17733","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The thread that gets the DLL_PROCESS_DETACH notification is not necessarily the one that got the DLL_PROCESS_ATTACH notification. This is obvious if you think about it, because the thread that got the DLL_PROCESS_ATTACH notification might not even exist any longer when the DLL is unloaded. How can something that doesn&#8217;t exist send a notification? Even so, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17733","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=17733"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17733\/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=17733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}