{"id":34253,"date":"2005-09-12T10:00:14","date_gmt":"2005-09-12T10:00:14","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/09\/12\/understanding-the-consequences-of-wait_abandoned\/"},"modified":"2005-09-12T10:00:14","modified_gmt":"2005-09-12T10:00:14","slug":"understanding-the-consequences-of-wait_abandoned","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050912-14\/?p=34253","title":{"rendered":"Understanding the consequences of WAIT_ABANDONED"},"content":{"rendered":"<p><P>\nOne of the important distinctions between mutexes and the other\nsynchronization objects is that mutexes have owners.\nIf the thread that owns a mutex exits without releasing the mutex,\nthe mutex is automatically released on the thread&#8217;s behalf.\n<\/P>\n<P>\nBut if this happens, you&#8217;re in big trouble.\n<\/P>\n<P>\nOne thing many people gloss over is the\n<CODE>WAIT_ABANDONED<\/CODE> return value\nfrom the synchronization functions such as\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/dllproc\/base\/waitforsingleobject.asp\">\n<CODE>WaitForSingleObject<\/CODE><\/a>.\nThey typically treat this as a successful wait,\nbecause it does mean that the object was obtained,\nbut it also tells you that the previous owner left the\nmutex abandoned and that the system had to release it on\nthe owner&#8217;s behalf.\n<\/P>\n<P>\nWhy are you in big trouble when this happens?\n<\/P>\n<P>\nPresumably, you created that mutex to protect multiple threads\nfrom accessing a shared object while it is an unstable state.\nCode enters the mutex, then starts manipulating the object,\ntemporarily making it unstable, but eventually restabilizing\nit and then releasing the mutex so that the next person can access\nthe object.\n<\/P>\n<P>\nFor example, you might have code that manages an\nanchored doubly-linked list\nin shared memory that goes like this:\n<\/P>\n<PRE>\nvoid MyClass::ReverseList()\n{\n WaitForSingleObject(hMutex, INFINITE);\n int i = 0; \/\/ anchor\n do {\n  int next = m_items[i].m_next;\n  m_items[i].m_next = m_items[i].m_prev;\n  m_items[i].m_prev = next;\n  i = next;\n } while (i != 0);\n ReleaseMutex(hMutex);\n}\n<\/PRE>\n<P>\nThere is nothing particularly exciting going on.\nBasic stuff, right?\n<\/P>\n<P>\nBut what if the program crashes while holding the mutex?\n(If you believe that your programs are bug-free,\nconsider the possiblity that the program is running\nover the network and the network goes down, leading\nto an in-page exception.\nOr simply that the user went to Task Manager\nand terminated your program while this function is running.)\n<\/P>\n<P>\nIn that case, the mutex is automatically released\nby the operating system,\nleaving the linked list in a corrupted state.\nThe next program to claim\nthe mutex will receive <CODE>WAIT_ABANDONED<\/CODE> as the\nstatus code.\nIf you ignore that status code,\nyou end up operating on a corrupted linked list.\nDepending on how that linked list is used, it may\nresult in a resource leak or the system creating an\nunintended second copy of something, or perhaps even a crash.\nThe unfortunate demise of one program causes other programs\nto start behaving strangely.\n<\/P>\n<P>\nThen again, the question remains,\n&#8220;What do you do, then, if you get <CODE>WAIT_ABANDONED<\/CODE>?&#8221;\nThe answer is, &#8220;Good question.&#8221;\n<\/P>\n<P>\nYou might try to repair the corruption, if you keep enough\nauxiliary information around to recover a consistent state.\nYou might even design your data structures to be transactional,\nso that the death of a thread manipulating the data structures\ndoes not leave them in a corrupted state.\nOr you might just decide that since things are corrupted,\nyou should throw away everything and start over,\nlosing the state of work in progress, but at least allowing\nnew work to proceed unhindered.\n<\/P>\n<P>\nOr you might simply choose to ignore the error and continue\nonwards with a corrupt data structure, hoping that whatever\nwent wrong won&#8217;t result in cascade failures down the line.\nThis is what most people do, though usually without even being\naware that they&#8217;re doing it.\nAnd it&#8217;s really hard to debug the crashes that result from this\napproach.\n<\/P>\n<P>\n<STRONG>Exercise<\/STRONG>:\nWhy did we use indices instead of pointers in our\nlinked list data structure?\n<\/P>\n<P>\n[Raymond is currently away; this message was pre-recorded.]\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the important distinctions between mutexes and the other synchronization objects is that mutexes have owners. If the thread that owns a mutex exits without releasing the mutex, the mutex is automatically released on the thread&#8217;s behalf. But if this happens, you&#8217;re in big trouble. One thing many people gloss over is the WAIT_ABANDONED [&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-34253","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>One of the important distinctions between mutexes and the other synchronization objects is that mutexes have owners. If the thread that owns a mutex exits without releasing the mutex, the mutex is automatically released on the thread&#8217;s behalf. But if this happens, you&#8217;re in big trouble. One thing many people gloss over is the WAIT_ABANDONED [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/34253","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=34253"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/34253\/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=34253"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=34253"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=34253"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}