{"id":11713,"date":"2011-01-20T07:00:00","date_gmt":"2011-01-20T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/01\/20\/how-to-turn-off-the-exception-handler-that-com-helpfully-wraps-around-your-server\/"},"modified":"2011-01-20T07:00:00","modified_gmt":"2011-01-20T07:00:00","slug":"how-to-turn-off-the-exception-handler-that-com-helpfully-wraps-around-your-server","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110120-00\/?p=11713","title":{"rendered":"How to turn off the exception handler that COM &#034;helpfully&#034; wraps around your server"},"content":{"rendered":"<p>\nHistorically, COM\nplaced a giant <code>try\/except<\/code> around your server&#8217;s methods.\nIf your server encountered what would normally be an unhandled exception,\nthe giant <code>try\/except<\/code> would catch it and turn it into the\nerror <code>RPC_E_SERVERFAULT<\/code>.\nIt then marked the exception as handled, so that the server\nremained running,\nthereby &#8220;improving robustness by keeping the server running\neven when it encountered a problem.&#8221;\n<\/p>\n<p>\nMind you, this was actually a disservice.\n<\/p>\n<p>\nThe fact that an unhandled exception occurred means that the server\nwas <i>in an unexpected state<\/i>.\nBy catching the exception and saying,\n&#8220;Don&#8217;t worry, it&#8217;s all good,&#8221;\nyou end up leaving a corrupted server running.\nFor example:\n<\/p>\n<pre>\nHRESULT CServer::DoOneWork(...)\n{\n CWork *pwork = m_listWorkPending.RemoveFirst();\n if (pwork) {\n   pwork-&gt;UpdateTimeStamp();\n   pwork-&gt;FrobTheWidget();\n   pwork-&gt;ReversePolarity();\n   pwork-&gt;UnfrobTheWidget();\n   m_listWorkDone.Add(pwork);\n }\n return S_OK;\n}\n<\/pre>\n<p>\nSuppose there&#8217;s a bug somewhere that causes\n<code>pwork-&gt;Reverse&shy;Polarity()<\/code> to crash.\nMaybe the problem is that the neutrons aren&#8217;t flowing,\nso there&#8217;s no polarity to reverse.\nMaybe the polarizer is not property initialized.\nWhatever, doesn&#8217;t matter what the problem is,\njust assume there&#8217;s a bug that prevents it from working.\n<\/p>\n<p>\nWith the global <code>try\/except<\/code>, COM catches the\nexception and returns <code>RPC_E_SERVERFAULT<\/code> back to the caller.\nYour server remains up and running, ready for another request.\nMind you, your server is also corrupted.\nThe widget never got unfrobbed,\nthe timestamp refers to work that never completed,\nand the <code>CWork<\/code> that you removed from the pending work list\ngot leaked.\n<\/p>\n<p>\nBut, hey, your server stayed up.\n<\/p>\n<p>\nA few hours later, the server starts returning <code>E_OUTOFMEMORY<\/code>\nerrors (because of all the leaked work items),\nyou get errors because there are too many outstanding frobs,\nand the client hangs because it&#8217;s waiting for a completion notification\non that work item that you lost track of.\nYou debug the server to see why everything is so screwed up,\nbut you can&#8217;t find anything wrong.\n&#8220;I don&#8217;t understand why we are leaking frobs.\nEvery time we frob a widget, there&#8217;s a call to unfrob right after it!&#8221;\n<\/p>\n<p>\nYou eventually throw up your hands in resignation.\n&#8220;I can&#8217;t figure it out.\nThere&#8217;s no way we can be leaking frobs.&#8221;\n<\/p>\n<p>\nEven worse, the inconsistent object state can be a security hole.\nAn attacker tricks you into reversing the polarity of a nonexistent\nneutron flow, which causes you to leave the widget frobbed by mistake.\nBingo, frobbing a widget makes it temporarily exempt from unauthorized\npolarity changes,\nand now the bad guys can change the polarity at will.\nNow you have to chase a security vulnerability where widgets\nare being left frobbed, and you still can&#8217;t find it.\n<\/p>\n<p>\nCatching all exceptions and letting the process continue running\nassumes that a server can recover from an unexpected failure.\nBut this is absurd.\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2009\/11\/13\/9921676.aspx\">\nYou already know that the server is unrecoverably toast: It crashed<\/a>!\n<\/p>\n<p>\nMuch better is to let the server crash\nso that the crash dump can be captured <i>at the point of the failure<\/i>.\nNow you have a fighting chance of figuring out what&#8217;s going on.\n<\/p>\n<p>\nBut how do you turn off that massive <code>try\/except<\/code>?\nYou didn&#8217;t put it in your code; COM created it for you.\n<\/p>\n<p>\nEnter\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa344211(VS.85).aspx\">\n<code>IGlobal&shy;Options<\/code><\/a>:\nSet the <code>COMGLB_EXCEPTION_HANDLING<\/code>\nproperty to\n<code>COMGLB_EXCEPTION_DONOT_HANDLE<\/code>,\nwhich means\n&#8220;Please don&#8217;t try to &#8216;help&#8217; me by catching all exceptions.\nIf a fatal exception occurs in my code, then go ahead and let the process\ncrash.&#8221;\nIn Windows&nbsp;7, you can ask for the even stronger\n<code>COMGLB_EXCEPTION_DONOT_HANDLE_ANY<\/code>,\nwhich means\n&#8220;Don&#8217;t even try to catch &#8216;nonfatal&#8217; exceptions.&#8221;\n<\/p>\n<p>\nWait, what&#8217;s a &#8216;fatal&#8217; exception?\n<\/p>\n<p>\nA &#8216;fatal&#8217; exception, at least as COM interprets it,\nis an exception like <code>STATUS_ACCESS_VIOLATION<\/code>\nor <code>STATUS_ILLEGAL_INSTRUCTION<\/code>.\n(A complete list is in this\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa379163(VS.85).aspx\">\nsample Rpc exception filter<\/a>.)\nOn the other hand a &#8216;nonfatal&#8217; exception is something like\na C++ exception or a CLR exception.\nYou probably want an unhandled C++ or CLR exception to crash your\nserver, too; after all, it would have crashed your program if it\nweren&#8217;t running as a server.\nTherefore, my personal recommendation is to use\n<code>COMGLB_EXCEPTION_DONOT_HANDLE_ANY<\/code>\nwhenever possible.\n<\/p>\n<p>\n&#8220;That&#8217;s great, but why is the default behavior the dangerous\n&#8216;silently swallow exceptions&#8217; mode?&#8221;\n<\/p>\n<p>\nThe COM folks have made numerous attempts to change the default\nfrom the dangerous mode to one of the safer modes,\nbut the application compatibility consequences have always been too great.\nTurns out there are a lot of servers that actually rely on COM silently\nmasking their exceptions.\n<\/p>\n<p>\nBut at least now you won&#8217;t be one of them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Historically, COM placed a giant try\/except around your server&#8217;s methods. If your server encountered what would normally be an unhandled exception, the giant try\/except would catch it and turn it into the error RPC_E_SERVERFAULT. It then marked the exception as handled, so that the server remained running, thereby &#8220;improving robustness by keeping the server running [&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-11713","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Historically, COM placed a giant try\/except around your server&#8217;s methods. If your server encountered what would normally be an unhandled exception, the giant try\/except would catch it and turn it into the error RPC_E_SERVERFAULT. It then marked the exception as handled, so that the server remained running, thereby &#8220;improving robustness by keeping the server running [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11713","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=11713"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11713\/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=11713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}