{"id":25283,"date":"2007-09-04T10:00:00","date_gmt":"2007-09-04T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/09\/04\/does-creating-a-thread-from-dllmain-deadlock-or-doesnt-it\/"},"modified":"2007-09-04T10:00:00","modified_gmt":"2007-09-04T10:00:00","slug":"does-creating-a-thread-from-dllmain-deadlock-or-doesnt-it","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070904-00\/?p=25283","title":{"rendered":"Does creating a thread from DllMain deadlock or doesn&#039;t it?"},"content":{"rendered":"<p>Let me get this out of the way up front: Creating a thread from <code>DllMain<\/code> is <a href=\"http:\/\/www.microsoft.com\/whdc\/driver\/kernel\/DLL_bestprac.mspx\"> not recommended<\/a>. The discussion here has to do with explaining the behavior you may observe if you violate this advice.\n <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/pages\/407234.aspx#430060\"> Commenter Pete points out that &#8220;according to Usenet&#8221; creating a thread in <code>DllMain<\/code> is supposed to deadlock<\/a>, but that&#8217;s not what he saw. All he saw was that the thread entry procedure was not called.\n I&#8217;m going to set aside what &#8220;according to Usenet&#8221; means.\n Recall how a thread starts up. When you call <code>CreateThread<\/code>, a kernel thread object is created and scheduled. Once the thread gets a chance to run, the kernel calls all the <code>DllMain<\/code> functions with the <code>DLL_THREAD_ATTACH<\/code> code. Once that&#8217;s done, the thread&#8217;s entry point is called.\n The issue with deadlocks is that all <code>DllMain<\/code> functions are serialized. At most one <code>DllMain<\/code> can be running at a time. Suppose a <code>DllMain<\/code> function is running and it creates a thread. As we noted above, a kernel thread object is created and scheduled, and the first thing the thread does is notify all the DLLs with <code>DLL_THREAD_ATTACH<\/code>. Since <code>DllMain<\/code> functions are serialized, the attempt to send out the <code>DLL_THREAD_ATTACH<\/code> notifications must wait until the current <code>DllMain<\/code> function returns.\n That&#8217;s why you observe that the new thread&#8217;s entry point doesn&#8217;t get called until after you return from <code>DllMain<\/code>. The new thread hasn&#8217;t even made it that far; it&#8217;s still working on the <code>DLL_THREAD_ATTACH<\/code> notifications. On the other hand, there is no actual deadlock here. The new thread will get itself off the ground once everybody else has finished doing their <code>DllMain<\/code> work.\n So what is this deadlock that Usenet talks about? If you&#8217;ve been following along, you should spot it easily enough.\n If your <code>DllMain<\/code> function creates a thread and then waits for the thread to do something (e.g., waits for the thread to signal an event that says that it has finished initializing, then you&#8217;ve created a deadlock. The <code>DLL_PROCESS_ATTACH<\/code> notification handler inside <code>DllMain<\/code> is waiting for the new thread to run, but the new thread can&#8217;t run until the <code>DllMain<\/code> function returns so that it can send a new <code>DLL_THREAD_ATTACH<\/code> notification.\n This deadlock is much more commonly seen in <code>DLL_PROCESS_DETACH<\/code>, where a DLL wants to shut down its worker threads and wait for them to clean up before it unloads itself. You can&#8217;t wait for a thread inside <code>DLL_PROCESS_DETACH<\/code> because that thread needs to send out the <code>DLL_THREAD_DETACH<\/code> notifications before it exits, which it can&#8217;t do until your <code>DLL_PROCESS_DETACH<\/code> handler returns.<\/p>\n<p> (It is for this thread cleanup case that the function <code>FreeLibraryAndExitThread<\/code> was created.) <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let me get this out of the way up front: Creating a thread from DllMain is not recommended. The discussion here has to do with explaining the behavior you may observe if you violate this advice. Commenter Pete points out that &#8220;according to Usenet&#8221; creating a thread in DllMain is supposed to deadlock, but that&#8217;s [&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-25283","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Let me get this out of the way up front: Creating a thread from DllMain is not recommended. The discussion here has to do with explaining the behavior you may observe if you violate this advice. Commenter Pete points out that &#8220;according to Usenet&#8221; creating a thread in DllMain is supposed to deadlock, but that&#8217;s [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25283","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=25283"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25283\/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=25283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=25283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=25283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}