<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>cbrumme's WebLog</title><link>http://blogs.msdn.com/b/cbrumme/</link><description /><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>A quick update on me.</title><link>http://blogs.msdn.com/b/cbrumme/archive/2006/09/15/756709.aspx</link><pubDate>Sat, 16 Sep 2006 01:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:756709</guid><dc:creator>cbrumme</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=756709</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2006/09/15/756709.aspx#comments</comments><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;It’s been over two years since I blogged.&amp;nbsp; Although I remain happily (perhaps even ecstatically) working at Microsoft, I left the CLR team and the Developer Division about a year ago.&amp;nbsp; I’m now on an incubation team, exploring evolution and revolution in operating systems.&amp;nbsp; This is a fascinating area that includes devices, concurrency, scheduling, security, distribution, application model, programming model and even some aspects of user interaction (where I am totally out of my depth).&amp;nbsp; And, as you might expect with my background, our effort also includes managed programming.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;Anyway, this blog will remain available indefinitely.&amp;nbsp; It continues to be useful for certain technical details which are unavailable elsewhere.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;In the meantime, if any readers are interested in working on a deep systems incubation with me and a team of truly outstanding developers, please send me email (cbrumme).&amp;nbsp; We are holding to some very high standards for this effort in terms of insight, experience and hard work.&amp;nbsp; But if you are like me, I am confident you will find it a dream opportunity.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=756709" width="1" height="1"&gt;</description></item><item><title>Updated Finalization and Hosting</title><link>http://blogs.msdn.com/b/cbrumme/archive/2004/04/26/120609.aspx</link><pubDate>Tue, 27 Apr 2004 00:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:120609</guid><dc:creator>cbrumme</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=120609</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2004/04/26/120609.aspx#comments</comments><description>&lt;P&gt;My original posts on Finalization and Hosting had some hokey XXXXX markers in place of content, where that content hadn't already been disclosed in some form.&amp;nbsp; Now that the Visual Studio 2005 Community Preview is available, I've gone back to those two posts and replaced the XXXXX markers with real text.&lt;/P&gt;
&lt;P&gt;Also, it's obviously been a while since my last post.&amp;nbsp; I started writing something this weekend, but the weather here has been spectacular and I was compelled to go outside and play.&amp;nbsp; I'll try to have something in the next couple of weeks.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=120609" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/Chat/">Chat</category></item><item><title>Hosting</title><link>http://blogs.msdn.com/b/cbrumme/archive/2004/02/21/77595.aspx</link><pubDate>Sat, 21 Feb 2004 18:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:77595</guid><dc:creator>cbrumme</dc:creator><slash:comments>57</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=77595</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2004/02/21/77595.aspx#comments</comments><description>&lt;FONT face=Tahoma size=2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Hosting&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;My prior three blogs were supposed to be on Hosting.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each time I got side tracked, first on Exceptions, then on Application Compatibility and finally on Finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I refuse to be side tracked this time&amp;#8230; much.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Also, I need to explain why it&amp;#8217;s taken so long to get this blog out.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Part of the reason is vacation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I spent Thanksgiving skiing in Whistler.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then I took a quick side trip to &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;Scottsdale&lt;/st1:place&gt;&lt;/st1:City&gt; for a friend&amp;#8217;s surprise birthday party and to visit my parents.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Finally, I spent over three weeks on Maui getting a break from the &lt;st1:place w:st="on"&gt;&lt;st1:City w:st="on"&gt;Seattle&lt;/st1:City&gt;&lt;/st1:place&gt; winter.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Another reason for the delay is writer&amp;#8217;s block.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This topic is so huge.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The internal specification for the Whidbey Hosting Interfaces is over 100 pages.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And that spec only covers the hosting interfaces themselves.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are many other aspects of hosting, like how to configure different security policy in different AppDomains, or how to use COM or managed C++ to stitch together the unmanaged host with the managed applications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There&amp;#8217;s no way I can cover the entire landscape.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Anyway, here goes. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Mostly I was tourist overhead at the PDC.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But one of the places I tried to pay for my ticket was a panel on Hosting.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The other panelists included a couple of Program Managers from the CLR, another CLR architect, representatives from Avalon / Internet Explorer, SQL Server, Visual Studio / Office, and &amp;#8211; to my great pleasure &amp;#8211; a representative from &lt;st1:mswterms w:st="on"&gt;IBM&lt;/st1:mswterms&gt; for DB2. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;One thing that was very clear at that panel is that the CLR team has done a poor job of defining what hosting is and how it is done.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Depending on your definition, hosting could be:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Mixing unmanaged and managed code in the same process.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Running multiple applications, each in its own specially configured AppDomain.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Using the unmanaged hosting interfaces described in mscoree.idl.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Configuring how the CLR runs in the process, like disabling the concurrent GC through an application config file.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Even though the hosting interfaces described in mscoree.idl are a small part of what &lt;I style="mso-bidi-font-style: normal"&gt;could&lt;/I&gt; be hosting, I&amp;#8217;m going to concentrate on those interfaces.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In V1 and V1.1 of the CLR, we provided some APIs that allowed an unmanaged process host to exercise some limited control over the CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This limited control included the ability to select the version of the CLR to load, the ability to create and configure AppDomains from unmanaged code, access to the ThreadPool, and a few other fundamental operations.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Also, we knew we eventually needed to support hosts which manage all the memory in the process and which use non-preemptive scheduling of tasks and perhaps even light-weight fibers rather than OS threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we added some rudimentary (and alas inadequate) APIs for fibers and memory control.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This invariably happens when you add features that you think you will eventually need, rather than features that someone is actually using and giving feedback on.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If you look closely at the V1 and V1.1 hosting APIs, you really see what we needed to support ASP.NET and a few other scenarios, like ones involving EnterpriseServices, Internet Explorer or VSA, plus some rudimentary guesses at what we might need to coexist properly inside SQL Server.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Obviously in Whidbey we have refined those guesses about SQL Server into hard requirements.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we tried very hard to generalize each extension that we added for SQL Server, so that it would be applicable to many other hosting scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, it&amp;#8217;s amazing that the SQL Server team still talks to us &amp;#8211; whenever they ask for anything, we always say No and give them something that works a lot better for other hosts and not nearly so well for SQL Server.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In our next release (Whidbey), we&amp;#8217;ve made a real effort to clean up the existing hosting support and to dramatically extend it for a number of new scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Therefore I&amp;#8217;m not going to spend any more time discussing those original V1 &amp;amp; V1.1 hosting APIs, except to the extent that they are still relevant to the following Whidbey hosting discussion.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Also I&amp;#8217;m going to skip over all the general introductory topics like &amp;#8220;When to host&amp;#8221; since they were the source of my writer&amp;#8217;s block.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, I&amp;#8217;m going to leap into some of the more technically interesting topics.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Maybe after we&amp;#8217;ve studied various details we can step back and see some general guidelines.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Threading and Synchronization&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;One of the most interesting challenges we struggled with during Whidbey was the need to cooperate with SQL Server&amp;#8217;s task scheduling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SQL Server can operate in either thread mode or fiber mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most customers run in thread mode, but SQL Server can deliver its best numbers on machines with lots of CPUs when it&amp;#8217;s running in fiber mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That gap between thread and fiber mode has been closing as the OS addresses issues with its own preemptive scheduler.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;A few years ago, I ran some experiments to see how many threads I could create in a single process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Not surprisingly, after almost 2000 threads I ran out of address space in the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because the default stack size on NT is 1 MB and the default user address space is 2 GB.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Starting with V1.1, the CLR can load into LARGEADDRESSAWARE processes and use up to 3 GB of address space).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you shrink the default stack size, you can create more than 2000 threads before hitting the address space limit.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I see stack sizes of 256 KB in the SQL Server process on my machine, clearly to reduce this impact on process address space.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Of course, address space isn&amp;#8217;t the only limit you can hit.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even on the 4 CPU server box I was experimenting with, the real memory on the system was inadequate for the working set being used.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With enough threads, I exceeded real memory and experienced paging.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Okay, it was actually thrashing).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But nowadays there are plenty of servers with several GB of real &amp;#8211; and real cheap &amp;#8211; memory, so this doesn&amp;#8217;t have to be an issue.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In my experiments, I simulated server request processing using an artificial work load that combined blocking, allocation, CPU-intensive computation, and a reasonable memory reference set using a mixture of both shared and per-request allocations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the first experiments, all the threads were ready to run and all of them had equal priority.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The result of this was that all threads were scheduled in a round-robin fashion on those 4 CPUs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since the Windows OS schedules threads preemptively, each thread would execute until it either needed to block or it exceeded its quantum.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With hundreds or even thousands of threads, each context switch was extremely painful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because most of the memory used by that thread was so cold in the cache, having been fully displaced by the hundreds of threads that ran before it.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;As we all know, modern CPUs are getting faster and faster at raw computation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And they have more and more memory available to them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But access to that memory is getting relatively slower each year.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By that, I mean that a single memory access costs the equivalent of an increasing number of instructions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One of the ways the industry tries to mitigate that relative slowdown is through a cache hierarchy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Modern X86 machines have L1, L2 and L3 levels of cache, ordered from fastest and smallest to slowest and largest.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;(Other ways we try to mitigate the slowdown is by increasing the locality of our data structures and by pre-fetching.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you are a developer, hopefully you already know about locality.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the unmanaged world, locality is entirely your responsibility.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the managed world, you get some locality benefits from our environment &amp;#8211; notably the garbage collector, but also the auto-layout of the class loader.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Yet even in managed code, locality remains a major responsibility of each developer).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Unfortunately, context switching between such a high number of threads will largely invalidate all those caches.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So I changed my simulated server to be smarter about dispatching requests.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead of allowing 1000 requests to execute concurrently, I would block 996 of those requests and allow 4 of them to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This makes life pretty easy for the OS scheduler!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are four CPUs and four runnable threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s pretty obvious which threads should run.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Not only will the OS keep those same four threads executing, it will likely keep them affinitized to the same CPUs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a thread moves from one CPU to another, the new CPU needs to fill all the levels of cache with data appropriate to the new thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, if we can remain affinitized, we can enjoy all the benefits of a warm cache.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OS scheduler attempts to run threads on the CPU that last ran them (soft affinity).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But in practice this soft affinity is too soft.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Threads tend to migrate between CPUs far more than we would like.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the OS only has 4 runnable threads for its 4 CPUs, the amount of migration seemed to drop dramatically.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Incidentally, Windows also supports hard affinity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a thread is hard affinitized to a CPU, it either runs on that CPU or it doesn&amp;#8217;t run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR can take advantage of this when the GC is executing in its server mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But you have to be careful not to abuse hard affinity. You certainly don&amp;#8217;t want to end up in a situation where all the &amp;#8220;ready to run&amp;#8221; threads are affinitized to one CPU and all the other CPUs are necessarily stalled.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Also, it&amp;#8217;s worth mentioning the impact of hyper-threading or NUMA on affinity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On traditional SMP, our choices were pretty simple.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Either our thread ran on its ideal processor, where we are most likely to see all the benefits of a warm cache, or it ran on some other processor.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All those other processor choices can be treated as equally bad for performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But with hyper-threading or NUMA, some of those other CPUs might be better choices than others.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of hyper-threading, some logical CPUs are combined into a single physical CPU and so they share access to the same cache memory at some level in the cache hierarchy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For NUMA, the CPUs may be arranged in partitions (e.g. hemispheres on some machines), where each partition has faster access to some memory addresses and slower access to other addresses.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In all these cases, there&amp;#8217;s some kind of gradient from the very best CPU(s) for a thread to execute on, down to the very worst CPU(s) for that particular thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The world just keeps getting more interesting.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Anyway, remember that my simulated server combined blocking with other operations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a real server, that blocking could be due to a web page making a remote call to get rows from a database, or perhaps it could be blocking due to a web service request.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If my server request dispatcher only allows 4 requests to be in flight at any time, such blocking will be a scalability killer.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I would stall a CPU until my blocked thread is signaled.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would be intolerable.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Many servers address this issue by releasing some multiple of the ideal number of requests simultaneously.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If I have 4 CPUs dedicated to my server process, then 4 requests is the ideal number of concurrent requests.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If there&amp;#8217;s &amp;#8220;moderate&amp;#8221; blocking during the processing of a typical request, I might find that 8 concurrent requests and 8 threads is a good tradeoff between more context switching and not stalling any CPUs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If I pick too high of a multiple over the number of CPUs, then context switching and cache effects will hurt my performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If I pick too low a multiple, then blocking will stall a CPU and hurt my performance.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If you look at the heuristics inside the managed ThreadPool, you&amp;#8217;ll find that we are constantly monitoring the CPU utilization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we notice that some CPU resources are being wasted, we may be starving the system by not doing enough work concurrently.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When this is detected, we are likely to release more threads from the ThreadPool in order to increase concurrency and make better use of the CPUs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a decent heuristic, but it isn&amp;#8217;t perfect.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, CPU utilization is &amp;#8220;backwards looking.&amp;#8221;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You actually have to stall a CPU before we will notice that more work should be executed concurrently.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And by the time we&amp;#8217;ve injected extra threads, the stalling situation may already have passed.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The OS has a better solution to this problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;IO Completion Ports have a direct link to the blocking primitives in Win32.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a thread is processing a work item from a completion port, if that thread blocks efficiently through the OS, then the blocking primitive will notify the completion port that it should release another thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Busy waiting instead of efficient blocking can therefore have a substantial impact on the amount of concurrency in the process).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This feedback mechanism with IO Completion Ports is far more immediate and effective than the CLR&amp;#8217;s heuristic based on CPU utilization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But in fairness I should point out that if a managed thread performs managed blocking via any of the managed blocking primitives (contentious Monitor.Enter, WaitHandle.WaitOne/Any/All, Thread.Join, GC.WaitForPendingFinalizers, etc.), then we have a similar feedback mechanism.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We just don&amp;#8217;t have hooks into the OS, so we cannot track all the blocking operations that occur in unmanaged code.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Of course, in my simulated server I didn&amp;#8217;t have to worry about &amp;#8220;details&amp;#8221; like how to track all OS blocking primitives.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, I postulated a closed world where all blocking had to go through APIs exposed by my server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This gave me accurate and immediate information about threads either beginning to block or waking up from a blocking operation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Given this information, I was able to tweak my request dispatcher so it avoided any stalling by injecting new requests as necessary.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Although it&amp;#8217;s possible to completely prevent stalling in this manner, it&amp;#8217;s not possible to prevent context switches.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Consider what happens on a 1 CPU machine.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We release exactly one request which executes on one thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When that thread is about to block, we release a second thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So far, it&amp;#8217;s perfect.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But when the first thread resumes from its blocking operation, we now have two threads executing concurrently.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Our request dispatcher can &amp;#8220;retire&amp;#8221; one of those threads as soon as it&amp;#8217;s finished its work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But until then we have two threads executing on a single CPU and this will impact performance.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I suppose we could try to get ruthless in this situation, perhaps by suspending one of the threads or reducing its priority.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In practice, it&amp;#8217;s never a good idea to suspend an executing thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that thread holds any locks that are required by other concurrent execution, we may have triggered a deadlock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Reducing the priority might help and I suspect I played around with that technique.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To be honest, I can&amp;#8217;t remember that far back.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;We&amp;#8217;ll see that SQL Server can even solve this context switching problem.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Oh yeah, SQL Server&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;So what does any of this have to do with SQL Server?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Not surprisingly, the folks who built SQL Server know infinitely more than me about how to get the best performance out of a server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And when the CLR is inside SQL Server, it must conform to their efficient design.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let&amp;#8217;s look at their thread mode, first.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fiber mode is really just a refinement over this.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Incoming requests are carried on threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SQL Server handles a lot of simultaneous requests, so there are a lot of threads in the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With normal OS &amp;#8220;free for all&amp;#8221; scheduling, this would result in way too many context switches, as we have seen.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So instead those threads are affinitized to a host scheduler / CPU combination.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The scheduler tries to ensure that there is one unblocked thread available at any time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All the other threads are ideally blocked.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This gives us the nirvana of 100% busy CPUs and minimal context switches.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To achieve this nirvana, all the blocking primitives need to cooperate with the schedulers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if an event has been signaled and a thread is considered by the application to be &amp;#8220;ready to run&amp;#8221;, the scheduler may not choose to release it, if the scheduler&amp;#8217;s corresponding CPU is already executing another thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this manner, the blocking primitive and the scheduler are tightly integrated.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;When I built my simulated server, I was able to achieve an ideal &amp;#8220;closed world&amp;#8221; where all the synchronization primitives were controlled by me.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SQL Server attempts the same thing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a thread needs to block waiting for a data page to be read, or for a page or row latch to be released, that blocking occurs through the SQL Server scheduler.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This guarantees that exactly one thread is available to run on each CPU, as we&amp;#8217;ve seen.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Of course, execution of managed code also hits various blocking points.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Monitor.Enter (&amp;#8216;lock&amp;#8217; in C# and &amp;#8216;SyncLock&amp;#8217; in VB.NET) is a typical case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Other cases include waiting for a GC to complete, waiting for class construction or assembly loading or type loading to occur, waiting for a method to be JITted, or waiting for a remote call or web service to return.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For SQL Server to hit their performance goals and to avoid deadlocks, the CLR must route all of these blocking primitives to SQL Server (or any other similar host) through the new Whidbey hosting APIs.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Leaving the Closed World&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;But what about synchronization primitives that are used for coordination with unmanaged code and which have precise semantics that SQL Server cannot hope to duplicate?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, WaitHandle and its subtypes (like Mutex, AutoResetEvent and ManualResetEvent) are thin wrappers over the various OS waitable handles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These primitives provide atomicity guarantees when you perform a WaitAll operation on them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They have special behavior related to message pumping.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And they can be used to coordinate activity across multiple processes, in the case of named primitives.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s unrealistic to route operations on WaitHandle through the hosting APIs to some equivalent host-provided replacements.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This issue with WaitHandle is part of a more general problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What happens if I PInvoke from managed code to an OS service like CoInitialize or LoadLibrary or CryptEncrypt?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Do those OS services block?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, I know that LoadLibrary will have to take the OS loader lock somewhere.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I could imagine that CoInitialize might need to synchronize something, but I have no real idea.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One thing I am sure of: if any blocking happens, it isn&amp;#8217;t going to go through SQL Server&amp;#8217;s blocking primitives and coordinate with their host scheduler.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The idealized closed world that SQL Server needs has just been lost.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The solution here is to alert the host whenever a thread &amp;#8220;leaves the runtime&amp;#8221;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, if we are PInvoking out, or making a COM call, or the thread is otherwise transitioning out to some unknown unmanaged execution, we tell the host that this is happening.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the host is tracking threads as closely as SQL Server does, it can use this event to disassociate the thread from the host scheduler and release a new thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This ensures that the CPU stays busy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because even if the disassociated thread blocks, we&amp;#8217;ve released another thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This newly released thread is still inside our closed world, so it will notify before it blocks so we can guarantee that the CPU won&amp;#8217;t stall.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Wait a second.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR did a ton of work to re-route most of its blocking operations through the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But we could have saved almost that entire ton of engineering effort if we had just detached the thread from the host whenever SQL Server called into managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That way, we could freely block and we wouldn&amp;#8217;t disrupt the host&amp;#8217;s scheduling decisions.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This is true, but it won&amp;#8217;t perform as well as the alternative. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Whenever a thread disassociates from a host scheduler, another thread must be released.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This guarantees that the CPU is busy, but it has sacrificed our nirvana of only having a single runnable thread per CPU.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now we&amp;#8217;ve got two runnable threads for this CPU and the OS will be preemptively context-switching between them as they run out of quantum.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If a significant amount of the processing inside a host is performed through managed code, this would have a serious impact on performance.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Indeed, if a significant amount of the processing inside a host is performed in unmanaged code, called via PInvokes or COM calls or other mechanisms that &amp;#8220;leave the runtime&amp;#8221;, this too can have a serious impact on performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But, for practical purposes, we expect most execution to remain inside the host or inside managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The amount of processing that happens in arbitrary unmanaged code should be low, especially over time as our managed platform grows to fill in some of the current gaps.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Of course, some PInvokes or COM calls might be to services that were exported from the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We certainly don&amp;#8217;t want to disassociate from the host scheduler every time the in-process &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; provider performs a PInvoke back to SQL Server to get some data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would be unnecessary and expensive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So there&amp;#8217;s a way for the host to control which PInvoke targets perform a &amp;#8220;leave runtime&amp;#8221; / &amp;#8220;return to runtime&amp;#8221; pair and which ones are considered to remain within the closed world of our integrated host + runtime.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Even if we were willing to tolerate the substantial performance impact of considering all of the CLR to be outside the host&amp;#8217;s closed world (i.e. we disassociated from the host&amp;#8217;s scheduler whenever we ran managed code), this approach would be inadequate when running in fiber mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because of the nasty effects which thread affinity can have on a fiber-based system.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Fiber Mode&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;As we&amp;#8217;ve seen, SQL Server and other &amp;#8220;extreme&amp;#8221; hosts can ensure that at any time each CPU has only a single thread within the closed world that is ready to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But when SQL Server is in thread mode, there are still a large number of threads that aren&amp;#8217;t ready to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It turns out that all those blocked threads impose a modest cost upon the OS preemptive scheduler.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And that cost becomes an increasing consideration as the number of CPUs increases.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For 1, 2, 4 and probably 8 CPU machines, fiber mode isn&amp;#8217;t worth the headaches we&amp;#8217;re about to discuss.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But by the time you get to a larger machine, you might achieve something like a 20% throughput boost by switching to fiber mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(I haven&amp;#8217;t seen real numbers in a year or two, so please take that 20% as a vague ballpark).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Fiber mode simply eliminates all those extra threads from any consideration by the OS.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you stay within the idealized nirvana (i.e. you don&amp;#8217;t perform a &amp;#8220;leave runtime&amp;#8221; operation), there is only one thread for each host scheduler / CPU.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, there are many stacks / register contexts and each such stack / register context corresponds to an in-flight request.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a stack is ready to run, the single thread switches away from whatever stack it was running and switches to the new stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But from the perspective of the OS scheduler, it just keeps running the only thread it knows about.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;So in both thread mode and fiber mode, SQL Server uses non-preemptive host scheduling of these tasks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This scheduling happens in user mode, which is a distinct advantage over the OS preemptive scheduling which happens in kernel mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The only difference is whether the OS scheduler is aware of all the tasks on the host scheduler, or whether they all look like a single combined thread &amp;#8211; albeit with different stacks and register contexts.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;But the impact of this difference is significant.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, it means that there is an M:N relationship between stacks (logical CLR threads) and OS threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is M:N because multiple stacks will execute on a single thread, and because the specially nominated thread that carries those stacks can change over time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This change in the nominated thread occurs as a consequence of those &amp;#8220;leave runtime&amp;#8221; calls.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Remember that when a thread leaves the runtime, we inform the host which disassociates the thread from the host scheduler.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A new thread is then created or obtained from a short list of already-created threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This new thread then picks up the next stack that is ready to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The effect is that this stack has migrated from the original disassociated thread to the newly nominated thread.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This M:N relationship between stacks and OS threads causes problems everywhere that thread affinity would normally occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;ve already mentioned CPU affinity when discussing how threads are associated with CPUs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But now I&amp;#8217;m talking about a different kind of affinity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thread affinity is the association between various programmatic operations and the thread that these operations must run on.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if you take an OS critical section by calling EnterCriticalSection, the resulting ownership is tied to your thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Sometimes developers say that the OS critical section is scoped to your thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You must call LeaveCriticalSection from that same thread.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;None of this is going to work properly if your logical thread is asynchronously and apparently randomly migrating between different physical threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You&amp;#8217;ll successfully take the critical section on one logical thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you attempt to recursively acquire this critical section, you will deadlock if a migration has intervened.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because it will look like a different physical thread is actually the owner.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Imagine writing some hypothetical code inside the CLR:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;EnterCriticalSection(pCS);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;If (pGlobalBlock == NULL)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;pGlobalBlock = Alloc(count);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;LeaveCriticalSection(pCS);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Obviously any real CLR code would be full of error handling, including a &amp;#8216;finally&amp;#8217; clause to release the lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we don&amp;#8217;t use OS critical sections directly since we typically reflect them to an interested host as we&amp;#8217;ve discussed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we instrument a lot of this stuff, including spinning during lock acquisition.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we wrap the locks with lots of logic to avoid deadlocks, including GC-induced deadlocks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But let&amp;#8217;s ignore all of the goop that would be necessary for real CLR code.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;It turns out that the above code has a thread affinity problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even though SQL Server&amp;#8217;s fiber scheduling is non-preemptive, scheduling decisions can still occur whenever we call into the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For reasons that I&amp;#8217;ll explain later, all memory allocations in the CLR have the potential to call into the host and result in scheduling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously most allocations will be satisfied locally in the CLR without escalation to the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And most escalations to the host still won&amp;#8217;t cause a scheduling decision to occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But from a correctness perspective, all allocations have the potential to cause scheduling.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Other places where thread affinity can bite us include:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;The OS Mutex and the managed System.Threading.Mutex wrapper.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;LoadLibrary and DllMain interactions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As I&amp;#8217;ve explained in my blog entry on Shutdown, DllMain notifications occur on a thread which holds the OS loader lock.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;TLS (thread local storage).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s worth mentioning that, starting with Windows Server 2003, there are new FLS (fiber local storage) APIs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These APIs allow you to associate state with the logical rather than the physical thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a fiber is associated with a thread for execution (SwitchToFiber), the FLS is automatically moved from the fiber onto the thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For managed TLS, we now move this automatically.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But we cannot do this unconditionally for all the unmanaged TLS.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;Thread culture or locale, the impersonation context or user identity, the COM+ transaction context, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In some sense, these are just special cases of thread local storage.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, for historical reasons it isn&amp;#8217;t possible to solve these problems by moving them to FLS.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;Taking control of a thread for GC, Abort, etc. via the OS SuspendThread() service.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;Any use of ThreadId or Thread Handle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This includes all debugging.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;&amp;#8220;Hand-rolled&amp;#8221; locks that we cannot discover or reason about, and which you have inadvertently based on the physical OS thread rather than the logical thread or fiber.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo2; tab-stops: list .5in"&gt;Various PInvokes or COM calls that might end up in unmanaged code with affinity requirements.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, MSHTML can only be called on STA threads which are necessarily affinitized.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, there is no list of all the APIs that have odd threading behavior.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s a minefield out there.&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Solving affinity issues is relatively simple.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The hard part is identifying all the places.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that the last two bullet items are actually the application&amp;#8217;s responsibility to identify.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some application code might appear to execute correctly when logical threads and OS threads are 1:1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But when a host creates an M:N relationship, any latent application bugs will be exposed.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In many cases, the easiest solution to a thread affinity issue is to disassociate the thread from the host&amp;#8217;s scheduler until the affinity is no longer required.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The hosting APIs provide for this, and we&amp;#8217;ve taken care of it for you in many places &amp;#8211; like System.Threading.Mutex.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Before we finish our discussion of locking, there&amp;#8217;s one more aspect worth mentioning.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In an earlier blog, I have mentioned the limited deadlock detection and deadlock breaking which the CLR performs when executing class constructors or JITting.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Except for this limited case, the CLR doesn&amp;#8217;t concern itself with application-level deadlocks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you write some managed code that takes a set of locks in random order, resulting in a potential deadlock, we consider that to be your application bug.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But some hosts may be more helpful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, SQL Server has traditionally detected deadlocks in all data accesses.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a deadlock occurs, SQL Server selects a victim and aborts the corresponding transaction.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This allows the other requests implicated in the deadlock to proceed.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;With the new Whidbey hosting APIs, it&amp;#8217;s possible for the host to walk all contentious managed locks and obtain a graph of the participants.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This support extends to locking through our Monitor and our ReaderWriterLock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Clearly, an application could perform locking through other means.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, an AutoResetEvent can be used to simulate mutual exclusion.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it&amp;#8217;s not possible for such locks to be included in the deadlock algorithms, since there isn&amp;#8217;t a strong notion of lock ownership that we can use.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Once the host has selected a deadlock victim, it must cause that victim to abort its forward progress somehow.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the victim is executing managed code, some obvious ways to do this include failing the lock attempt (since the thread is necessarily blocking), aborting the thread, or even unloading the AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ll return to the implications of this choice in the section on Reliability below.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Finally, it&amp;#8217;s interesting to consider how one might get even better performance than what SQL Server has achieved.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ve seen how fiber mode eliminates all the extra threads, by multiplexing a number of stacks / register contexts onto a single thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What happens if we then eliminate all those fibers?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For a dedicated server, we can achieve even better performance by forcing all application code to maintain its state outside of a thread&amp;#8217;s stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This allows us to use a single thread per CPU which executes user requests by processing them on its single dedicated stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All synchronous blocking is eliminated by relying on asynchronous operations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The thread never yields while holding its stack pinned.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The amount of memory required to hold an in-flight request will be far less than a 256 KB stack reservation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the cost of processing an asynchronous completion through polling can presumably be less than the cost of a fiber context switch.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If all you care about is performance, this is an excellent way to build a server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if you need to accommodate 3&lt;SUP&gt;rd&lt;/SUP&gt; party applications inside the server, this approach is questionable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most developers have a difficult time breaking their logic into segments which can be separately scheduled with no stack dependencies.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s a tedious programming model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Also, the underlying Windows platform still contains a lot of blocking operations that don&amp;#8217;t have asynchronous variants available.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;WMI is one example.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Memory Management&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Servers must not page.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Like all rules, this one isn&amp;#8217;t strictly true.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is actually okay to page briefly now and then, when the work load transitions from one steady state to another.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if you have a server that is routinely paging, then you have driven that server beyond its capacity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You need to reduce the load on the server or increase the server&amp;#8217;s memory capacity.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;At the same time, it&amp;#8217;s important to make effective use of the memory capacity of a server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ideally, a database would store the entire database contents in memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would allow it to avoid touching the disk, except to write the durable log that protects it from data loss and inconsistency in the face of catastrophic failure.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, the 2 or 3 GB limit of Win32 is far too restrictive for most interesting databases.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(SQL Server can use AWE to escape this limit, at some cost).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And even the address limits of Win64 are likely to be exceeded by databases presently.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because Win64 does not give you a full 64 bits of addressing and databases are already heading into the petabytes.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;So a database needs to consider all the competing demands for memory and make wise decisions about which ones to satisfy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Historically, those demands have included the buffer cache which contains data pages, compiled query plans, and all those thread stacks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the CLR is loaded into the process, significant additional memory is required for the GC heap, application code, and the CLR itself.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;m not sure what techniques SQL Server uses to trade off the competing demands for memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some servers carve memory up based on fixed ratios for the different broad uses, and then rely on LRU within each memory chunk.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Other servers assign a cost to each memory type, which indicates how expensive it would be to regenerate that memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, in the case of a data page, that cost is an IO.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Some servers use elaborate throttling of inbound requests, to keep the memory load reasonable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is relatively easy to do when all requests are comparable in terms of their memory and CPU requirements.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if some queries access a single database page and other queries touch millions of rows, it would be hard to factor this into a throttling decision that is so far upstream from the query processor.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, SQL Server tends to accept a large number of incoming requests and process them &amp;#8220;concurrently.&amp;#8221;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ve already seen in great detail why this concurrent execution doesn&amp;#8217;t actually result in preemptive context switching between all the corresponding tasks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it is still the case that each request will hold onto some reference set of memory, even when the host&amp;#8217;s non-preemptive scheduler has that request blocked.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If enough requests are blocked while holding onto significant unshared memory, then the server process may find itself over-committed on memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At this point, it could page &amp;#8211; which hurts performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it could kill some of the requests and free up the resources they are holding onto.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is an unfortunate situation, because we&amp;#8217;ve presumably already devoted resources like the CPU to get the request to its current state of partial completion.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we throw away the request, all that work was wasted.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the client is likely to resubmit the request, so we will have to repeat all that work soon.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Nevertheless, if the server is over-committed and it&amp;#8217;s not practical to recover more memory by e.g. shrinking the number of pages devoted to the buffer cache, then killing in-flight requests is a sound strategy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is particularly reasonable in database scenarios, since the transactional nature of database operations means that we can kill requests at any time and with impunity.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Unfortunately, the world of arbitrary managed execution has no transactional foundation we can rely on.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ll pick up this issue again below, in the section on Reliability.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;It should be obvious that, if SQL Server or any other host is going to make wise decisions about memory consumption on a &amp;#8220;whole process&amp;#8221; basis, that host needs to know exactly how much memory is being used and for what purposes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, before the host unloads an AppDomain as a way of backing out of an over-committed situation, the host needs some idea of how many megabytes this unload operation is likely to deliver.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In the reverse direction, the host needs to be able to masquerade as the operating system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, the CLR&amp;#8217;s GC monitors system memory load and uses this information in its heuristics for deciding when to schedule a collection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The host needs a way to influence these collection decisions.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;SQL Server and ASP.NET&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Clearly a lot of work went into threading, synchronization and memory management in SQL Server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One obvious question to ask is how ASP.NET compares.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They are both server products from Microsoft and they both execute managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Why didn&amp;#8217;t we need to add all this support to the hosting interfaces in V1 of the CLR, so we could support ASP.NET?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I think it&amp;#8217;s fair to say that ASP.NET took a much simpler approach to the problem of building a scalable server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To achieve efficient threading, they rely on the managed ThreadPool&amp;#8217;s heuristics to keep the CPUs busy without driving up too many context switches.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And since the bulk of memory allocations are due to the application, rather than the ASP.NET infrastructure (in other words, they aren&amp;#8217;t managing large shared buffer pools for data pages), it&amp;#8217;s not really possible for ASP.NET to act as a broker for all the different memory consumers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, they just monitor the total memory load, and recycle the worker process if a threshold is exceeded.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;(Incidentally, V1 of ASP.NET and the CLR had an unfortunate bug with the selection of this threshold.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The default point at which ASP.NET would recycle the process was actually a lower memory load than the point at which the CLR&amp;#8217;s GC would switch to a more aggressive schedule of collections.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we were actually killing the worker process before the CLR had a chance to deliver more memory back to the application.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Presumably in Whidbey this selection of default thresholds is now coordinated between the two systems.)&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;How can ASP.NET get away with this simpler approach?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;It really comes down to their fundamental goals.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;ASP.NET can scale out, rather than having to scale up.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you have more incoming web traffic, you can generally throw more web servers at the problem and load balance between them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whereas SQL Server can only scale out if the data supports this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In some cases, it does.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There may be a natural partitioning of the data, like access to the HotMail mailbox for a particular incoming user.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But in too many other cases, the data cannot be sufficiently partitioned and the server must be scaled up.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On X86 Windows, the practical limit is a 32-way CPU with a hard limit of 3 GB of user address space.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you want to keep increasing your work load on a single box, you need to use every imaginative trick &amp;#8211; like fibers or AWE &amp;#8211; to eke out all possible performance.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;There&amp;#8217;s also an availability issue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;ASP.NET can recycle worker processes quite quickly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if they have scaled out, recycling a worker process on one of the computers in the set will have no visible effect on the availability of the set of servers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But SQL Server may be limited to a single precious process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that process must be recycled, the server is unavailable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And recycling a database is more expensive than recycling a stateless ASP.NET worker process, because transaction logs must be replayed to move the database forwards or backwards to a consistent state.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The short answer is, ASP.NET didn&amp;#8217;t have to do all the high tech fancy performance work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whereas SQL Server was forced down this path by the nature of the product they must build.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Reliability&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Well, if you haven&amp;#8217;t read my earlier blogs on asynchronous exceptions, or if &amp;#8211; like me &amp;#8211; you read the Reliability blog back in June and don&amp;#8217;t remember what it said &amp;#8211; you might want to review it quickly at &lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/06/23/51482.aspx"&gt;http://blogs.msdn.com/cbrumme/archive/2003/06/23/51482.aspx&lt;/A&gt;.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The good news is that we&amp;#8217;ve revisited the rules for ThreadAbortException in Whidbey, so that there is now a way to abort a thread without disturbing any backout code that it is currently running.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it&amp;#8217;s still the case that asynchronous exceptions can intrude at fairly arbitrary spots in the execution.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Anyway, the availability goals of SQL Server place some rather difficult requirements on the CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Sure, we were pretty solid in V1 and V1.1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We ran a ton of stress and &amp;#8211; if you avoided stack overflow, running out of memory, and any asynchronous exceptions like Thread.Abort &amp;#8211; we could run applications indefinitely.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We really were very clean.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;One problem with this is that &amp;#8220;indefinitely&amp;#8221; isn&amp;#8217;t long enough for SQL Server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They have a noble goal of chasing 5 9&amp;#8217;s and you can&amp;#8217;t get there with loose statements like &amp;#8220;indefinitely&amp;#8221;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Another problem is that we can no longer exclude OutOfMemoryException and ThreadAbortException from our reliability profile.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ve already seen that SQL Server tries to use 100% of memory, without quite triggering paging.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The effect is that SQL Server is always on the brink of being out of memory, so allocation requests are frequently being denied.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Along the same lines, if the server is loaded it will allow itself to become over-committed on all resources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One strategy for backing out of an over-commitment is to abort a thread (i.e. kill a transaction) or possibly unload one or more AppDomains.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Despite this stressful abuse, at no time can the process terminate.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The first step to achieve this was to harden the CLR so that it was resilient to any resource failures.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fortunately we have some extremely strong testers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One tester built a system to inject a resource failure in every allocator, for every unique logical call stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This tests every distinct backout path in the product.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This technique can be used for unmanaged and managed (FX) code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That same tester is also chasing any unmanaged leaks by applying the principles of a tracing garbage collector to our unmanaged CLR data structures.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This technique has already exposed a small memory leak that we shipped in V1 of the CLR &amp;#8211; for the &amp;#8220;Hello World&amp;#8221; application!&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;With testers like that, you better have a strong development team too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At this point, I think we&amp;#8217;ve annotated the vast majority of our unmanaged CLR methods with reliability contracts.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These are a bit like Eiffel pre- and post-conditions and they provide machine-verifiable statements about each method&amp;#8217;s behavior with respect to GC, exceptions, and other fundamental operations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These contracts can be used during test coverage (and, in some cases, during static scans of the binary images) to test for conformance.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The bottom line is that the next release of CLR should be substantially more robust in the face of resource errors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Leaving aside stack overflows and focusing entirely on the unmanaged runtime, we are shooting for perfection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even for stack overflow, we expect to get very, very close.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we have the mechanisms in place that allow us to be rigorous in chasing after these goals.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;But what about all of the managed code?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Will FX be as robust as the unmanaged CLR?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And how can we possibly hold 3&lt;SUP&gt;rd&lt;/SUP&gt; party authors of stored procedures or user defined functions to that same high bar?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We want to enable a broad class of developers to write this sort of code, and we cannot expect them to perform many hundreds of hours of stress testing and fault injection on each new stored procedure.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we&amp;#8217;re chasing 5 9&amp;#8217;s by requiring every external developer to write perfect code, we should just give up now.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Instead, SQL Server relies on something other than perfect code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Consider how SQL Server worked before it started hosting the CLR:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The vast majority of execution inside SQL Server was via Transact SQL or TSQL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any application written in TSQL is inherently scalable, fiber-aware, and robust in the face of resource errors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any computation in TSQL can be terminated with a clean transaction abort.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Unfortunately, TSQL isn&amp;#8217;t expressive enough to satisfy all application needs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So the remaining applications were written in extended stored procedures or xprocs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These are typically unmanaged C++.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Their authors must be extremely sophisticated, because they are responsible for integrating their execution with the unusual threading environment and resource rules that exist inside SQL Server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Throw in the rules for data access and security (which I won&amp;#8217;t be discussing in this blog) and it takes superhuman knowledge and skill to develop a bug-free xproc. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In other words, you had a choice of well-behaved execution and limited expression (TSQL), or the choice of arbitrary execution coupled with a very low likelihood that you would get it right (xprocs).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;One of the shared goals of the SQL Server and CLR teams in Whidbey was to eliminate the need for xprocs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We wanted to provide a spectrum of choices to managed applications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Whidbey, that spectrum consists of three buckets for managed code:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo3; tab-stops: list .5in"&gt;&lt;B&gt;Safe&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;Code in this bucket is the most constrained. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;In fact, the host constrains it beyond what the CLR would normally allow to code that&amp;#8217;s only granted SecurityPermissionFlag.Execution.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So this code must be verifiably typesafe and has a reduced grant set.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it is further constrained from defining mutable static fields, from creating or controlling threads, from using the threadpool, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The goal here is to guide the code to best practices for scalability and robustness within the SQL Server or similar hosted environments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of SQL Server, this means that all state should be stored in the database and that concurrency is controlled through transactions against the data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, it&amp;#8217;s important to realize that these additional constraints are not part of the Security system and they may well be subvertible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The constraints are simply speedbumps (not roadblocks) which guide the application code away from potentially non-scalable coding techniques and which encourage best practices.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo3; tab-stops: list .5in"&gt;&lt;B&gt;External Access&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;Code in this bucket should be sufficient for replacing most xprocs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Such code must also be verifiably typesafe, but it is granted some additional permissions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The exact set of permissions is presumably subject to change until &lt;st1:State w:st="on"&gt;&lt;st1:place w:st="on"&gt;Yukon&lt;/st1:place&gt;&lt;/st1:State&gt; ships, but it&amp;#8217;s likely to allow access to the registry, the file system, and the network.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo3; tab-stops: list .5in"&gt;&lt;B&gt;Unsafe&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;This is the final managed escape hatch for writing code inside SQL Server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This code does not have to be verifiable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It has FullTrust (with the possible exception of UIPermission, which makes no sense within the database).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that it can do anything the most arbitrary xproc can do.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, it is much more likely to work properly, compared to that xproc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, it sits on top of a framework that has been designed to work inside the database.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Second, the code has all the usual benefits of managed code, like a memory manager that&amp;#8217;s based on accurate reachability rather than on programmer correctness.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Finally, it is executing on a runtime that understands the host&amp;#8217;s special rules for resource management, synchronization, threading, security, etc.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;For code in the Safe bucket, you may be wondering how a host could constrain code beyond SecurityPermissionFlag.Execution.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are two techniques available for this:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo4; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;Any assembly in the &amp;#8216;Safe&amp;#8217; subset could be scanned by a host-provided pre-verifier, to check for any questionable programming constructs like the definition of mutable static fields, or the use of reflection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This raises the obvious question of how the host can interject itself into the binding process and guarantee that only pre-verified assemblies are loaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The new Whidbey hosting APIs contain a Fusion loader hook mechanism, which allows the host to abstract the notion of an assembly store, without disturbing all our normal loader policy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can think of this as the natural evolution of the AppDomain.AssemblyResolve event.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SQL Server can use this mechanism to place all application assemblies into the database and then deliver them to the loader on demand.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In addition to enabling pre-verification, the loader hooks can also be used to ensure that applications inside the database are not inadvertently broken or influenced by changes outside the database (e.g. changes to the GAC).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, you could even copy a database from one machine to another and theoretically this could automatically transfer all the assemblies required by that database.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo4; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;The Whidbey hosting APIs provide controls over a new Host Protection Attribute (HPA) feature.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Throughout our frameworks, we&amp;#8217;ve decorated various unprotected APIs with an appropriate HPA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These HPAs indicate that the decorated API performs a sensitive operation like Synchronization or Thread Control.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, use of the ThreadPool isn&amp;#8217;t considered a secure operation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(At some level, it is a risk for Denial of Service attacks, but DOS remains an open design topic for our managed platform).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If code is running outside of a host that enables these HPAs, they have no effect.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Partially trusted code, including code that only has Execution permission, can still call all these APIs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if a host does enable these attributes, then code with insufficient trust can no longer call these APIs directly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indirect calls are still permitted, and in this sense the HPA mechanism is similar to the mechanism for LinkDemands.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Although HPAs use a mechanism that is similar to LinkDemands, it&amp;#8217;s very important to distinguish the HPA feature &amp;#8211; which is all about programming model guidance &amp;#8211; from any Security feature.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A great way to illustrate this distinction is Monitor.Enter.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Ignoring HPAs, any code can call Monitor.Enter and use this API to synchronize with other threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Naturally, SQL Server would prefer that most developers targeting their environment (including all the na&amp;#239;ve ones) should rely on database locks under transaction control for this sort of thing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Therefore they activate the HPA on this class:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;[&lt;SPAN style="COLOR: red"&gt;HostProtection(Synchronization=true, ExternalThreading=true)&lt;/SPAN&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public sealed class Monitor &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;[MethodImplAttribute(MethodImplOptions.InternalCall)]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public static extern void &lt;SPAN style="COLOR: red"&gt;Enter&lt;/SPAN&gt;(Object obj);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;However, devious code in the &amp;#8216;Safe&amp;#8217; bucket could use a HashTable as an alternate technique for locking.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you create a synchronized HashTable and then perform inserts or lookups, your Object.Equals and GetHashCode methods will be called within the lock that synchronizes the HashTable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The BCL developers were smart enough to realize this, and they added another HPA:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public class Hashtable : IDictionary, ISerializable,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;IDeserializationCallback, ICloneable&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;[HostProtection(Synchronization=true)]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public static Hashtable &lt;SPAN style="COLOR: red"&gt;Synchronized&lt;/SPAN&gt;(Hashtable table) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;if (table==null)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;throw new ArgumentNullException("table");&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;return new SyncHashtable(table);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Are there other places inside the frameworks where it&amp;#8217;s possible to trick an API into providing synchronization for its caller?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Undoubtedly there are, but we aren&amp;#8217;t going to perform exhaustive audits of our entire codebase to discover them all.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As we find additional APIs, we will decorate them with HPAs, but we make no guarantees here.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This would be an intolerable situation for a Security feature, but it&amp;#8217;s perfectly acceptable when we&amp;#8217;re just trying to increase the scalability and reliability of naively written database applications.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;Escalation Policy&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I chose the HPA on System.Threading.Monitor for a reason, in the above example.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you&amp;#8217;ve read my earlier blogs on Thread.Abort, you know that it&amp;#8217;s dangerous to asynchronously abort another thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That thread could be executing a class constructor, in which case that class is now unavailable throughout the AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That thread could be in the middle of an update to some shared application state, which would leave the application in an inconsistent state.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In V1 &amp;amp; V1.1, it was not really possible to write code that is robust in the face of asynchronous exceptions like Abort.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Whidbey, we&amp;#8217;re now introducing some constructs (Constrained Execution Regions and Critical Finalization) which make it possible to do this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;m not going to discuss those constructs in this blog.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But suffice it to say that, although it makes it possible to write entirely robust code, it doesn&amp;#8217;t make it easy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Without a higher level programmatic construct, like transactions, it&amp;#8217;s very difficult to write entirely robust code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You must acquire all the resources required for forward progress, tolerating exceptions during this acquisition phase.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then you enter a forward progress phase, which either cannot fail or which unconditionally triggers some compensating backout code upon failure.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If compensation is triggered, it must guarantee that the system is returned to a consistent state before it completes.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If you&amp;#8217;ve successfully written that sort of code, you know that it&amp;#8217;s an onerous discipline.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There&amp;#8217;s no way that we can expect the greater population of developers to write large bodies of bug-free code based on this plan.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;That&amp;#8217;s why, in V1 &amp;amp; V1.1, we recommend either using Abort on the current thread (in which case it is not asynchronous) or we recommend using it in conjunction with an AppDomain.Unload (in which case any inconsistent application state is likely to be discarded).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In Whidbey, it is possible to avoid inducing asynchronous Aborts onto threads that are performing backout (i.e. filter, finally, catch or fault blocks) or that hold locks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Our definition of a lock is pretty broad.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It includes execution of a class constructor, since all .cctor execution is synchronized according to elaborate rules by the CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It also includes Monitor.Enter, Mutex, ReaderWriterLock, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Finally, it includes any &amp;#8220;hand-rolled&amp;#8221; locks that you build, so long as you properly identify them to us.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Our rationale here is that any thread holding a lock may be updating shared state.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a thread isn&amp;#8217;t holding a lock, then any update it performs against shared state must be atomic or at least it never leaves that shared state in an inconsistent state.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is strictly a heuristic, but it&amp;#8217;s a pretty good one.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If we believe this heuristic, it means that we can use Abort without consequently unloading an AppDomain, if that thread doesn&amp;#8217;t hold any locks and isn&amp;#8217;t performing any backout.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it just so happens that the bulk of all managed code executing inside SQL Server is in the &amp;#8216;Safe&amp;#8217; subset &amp;#8211; which coincidentally is highly discouraged via HPAs from taking or holding locks.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In other words, code in the &amp;#8216;Safe&amp;#8217; subset can almost always take an asynchronous exception without affecting any of the execution on other threads in the same AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the case, even though that code was written by developers who don&amp;#8217;t understand the deep issues involved with asynchronous exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It further means that if we should catch such a thread at a point where it isn&amp;#8217;t safe to inject an asynchronous exception without also unloading the AppDomain, we can identify this window.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once this window is identified, we can either hold off from injecting the exception until this unsafe window has closed, or we can unload the entire AppDomain to eliminate the application inconsistency.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The host can decide whether to hold off on the injection or alternatively to proceed with an AppDomain unload, based on criteria like how resource-constrained the host is.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The hosting APIs for making these decisions imperatively would be rather complicated.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So the Whidbey hosting APIs provide a declarative mechanism called an escalation policy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This allows the host to express transitions and timeouts that take effect during error conditions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, SQL Server might state that any attempt to Abort a thread should delay if the victim thread holds a lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if that delay exceeds 30 seconds, the Abort attempt should be escalated to an AppDomain.Unload.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, the feature is more general than SQL Server&amp;#8217;s needs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, the V1 ASP.NET process recycling feature should now be expressible as a particular Whidbey escalation policy.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Winding down&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;As usual, I didn&amp;#8217;t get around to many of the interesting topics.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, those guidelines on when and how to host are noticeably absent.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I didn&amp;#8217;t explain how to do any simple stuff, like picking concurrent vs. non-concurrent vs. server GC.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The above text is completely free of any specific details of what our hosting APIs look like (partly because they are subject to change until Whidbey ships).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I didn&amp;#8217;t touch on any hosting topics outside of the hosting APIs, like all of the AppDomain considerations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As you can imagine, there&amp;#8217;s also plenty I could have said about Security.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, the hosting APIs allow the host to participate in role-based security and impersonation of Windows identities&amp;#8230;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Oh well.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Fortunately, one of the PMs involved in the Whidbey hosting effort is apparently writing a book on the general topic of hosting.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Presumably all these missing topics will be covered there.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And hopefully he won&amp;#8217;t run into the same issues with writer&amp;#8217;s block that I experienced on this topic.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;(Indeed, the event that ultimately resolved my writer&amp;#8217;s block was that my wife got the flu.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When she&amp;#8217;s not around, my weekends are boring enough for me to think about work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The reason I&amp;#8217;m posting two blogs this weekend is that Kathryn has gone to &lt;st1:place w:st="on"&gt;Maui&lt;/st1:place&gt; for the week and has left me behind.)&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Finally, the above blog talks about SQL Server a lot.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Hopefully it&amp;#8217;s obvious that the CLR wants to be a great execution environment for a broad set of servers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In V1, we focused on ASP.NET.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Based on that effort, we automatically worked well in many other servers with no additional work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, EnterpriseServices dropped us into their server processes simply by selecting the server mode of our GC.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Nothing else was required to get us running efficiently.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Well, we did a ton of other work in the CLR to support EnterpriseServices.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But that work was related to the COM+ programming model and infrastructure, rather than their server architecture.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We had to do that work whether we ran in their server process or were instead loading EnterpriseServices into the ASP.NET worker process or some other server).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In Whidbey we focused on extending the CLR to meet SQL Server&amp;#8217;s needs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But at every opportunity we generalized SQL Server&amp;#8217;s requirements and tried to build something that would be more broadly useful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Just as our ASP.NET work enabled a large number of base server hosting scenarios, we hope that our SQL Server work will enable a large number of advanced server hosting scenarios.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If you have a &amp;#8220;commercially significant&amp;#8221; hosting problem, whether on the server or the client, and you&amp;#8217;re struggling with how to incorporate managed code, I would be interested in hearing from you directly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Feel free to drop me an email with the broad outline of what you are trying to achieve, and I&amp;#8217;ll try to get you supported.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That support might be something as lame as some suggestions from me on how I would tackle the problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or at the other extreme, I could imagine more formal support and conceivably some limited feature work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That other extreme really depends on how commercially significant your product is and on how well our business interests align.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously decisions like that are far outside my control, but I can at least hook you up with the right people if this seems like a sensible approach.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Okay, one more &amp;#8216;Finally&amp;#8217;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;From time to time readers of my blog send me emails asking if there are jobs available on the CLR team.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At this moment, we do.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Drop me an email if you are interested.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s an extremely challenging team to work on, but the problems are truly fascinating.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=77595" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item><item><title>Finalization</title><link>http://blogs.msdn.com/b/cbrumme/archive/2004/02/20/77460.aspx</link><pubDate>Sat, 21 Feb 2004 06:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:77460</guid><dc:creator>cbrumme</dc:creator><slash:comments>94</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=77460</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2004/02/20/77460.aspx#comments</comments><description>&lt;SPAN style="COLOR: black; mso-bidi-font-weight: bold; mso-bidi-font-family: Tahoma"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-weight: bold; mso-bidi-font-family: Tahoma"&gt;Earlier this week, I wrote an internal email explaining how Finalization works in V1 / V1.1, and how it has been changed for Whidbey.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There&amp;#8217;s some information here that folks outside of Microsoft might be interested in.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-weight: bold; mso-bidi-font-family: Tahoma"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-weight: bold; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Costs&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Finalization is expensive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It has the following costs:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;1)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Creating a finalizable object is slower, because each such object must be placed on a RegisteredForFinalization queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In some sense, this is a bit like having an extra pointer-sized field in your object that the system initializes for you.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, our current implementation uses a slower allocator for every finalizable object, and this impact can be measured if you allocate small objects at a high rate.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;2)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Each GC must do a weak pointer scan of this queue, to find out whether any finalizable objects are now collectible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All such objects are then moved to a ReadyToFinalize queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The cost here is small.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;3)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;All objects in the ReadyToFinalize queue, and all objects reachable from them, are then marked.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that an entire graph of objects which would normally die in one generation can be promoted to the next generation, based on a single finalizable root to this graph.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that the size of this graph is potentially huge.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;4)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The older generation will be collected at some fraction of the frequency of the younger generation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(The actual ratio depends on your application, of course).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So promotion of the graph may have increased the time to live of this graph by some large multiple.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For large graphs, the combined impact of this item and #3 above will dominate the total cost of finalization.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;5)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;We currently use a single high priority Finalizer thread to walk the ReadyToFinalize queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This thread dequeues each object, executes its Finalize method, and proceeds to the next object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the one cost of finalization which customers actually expect.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;6)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Since we dedicate a thread to calling finalizers, we inflict an expense on every managed process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This can be significant in Terminal Server scenarios where the high number of processes multiplies the number of finalizer threads.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;7)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Since we only use a single thread for finalization, we are inherently non-scalable if a process is allocating finalizable objects at a high rate.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One CPU performing finalization might not keep up with 31 other CPUs allocating those finalizable objects.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;8)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The single finalizer thread is a scarce resource.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are various circumstances where it can become blocked indefinitely.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At that point, the process will leak resources at some rate and eventually die.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;See &lt;A href="http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx"&gt;&lt;SPAN style="COLOR: black"&gt;http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx&lt;/SPAN&gt;&lt;/A&gt; for extensive details.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;9)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Finalization has a conceptual cost to managed developers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In particular, it is difficult to write correct Finalize methods as I shall explain.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Eventually we would like to address #5 thru #8 above by scheduling finalization activity over our ThreadPool threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have also toyed with the idea of reducing the impact of #3 and #4 above, by pruning the graph based on reachability from your Finalize method and any code that it might call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Due to indirections that we cannot statically explore, like interface and virtual calls, it&amp;#8217;s not clear whether this approach will be fruitful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Also, this approach would cause an observable change in behavior if resurrection occurs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Regardless, you should not expect to see any of these possible changes in our next release.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Reachability&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;One of the guidelines for finalization is that a Finalize method shouldn&amp;#8217;t touch other objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;People sometimes incorrectly assume that this is because those other objects have already been collected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Yet, as I have explained, the entire reachable graph from a finalizable object is promoted.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;The real reason for the guideline is to avoid touching objects that may have already been finalized.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because finalization is unordered.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;So, like most guidelines, this one is made to be broken under certain circumstances.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, if your object &amp;#8220;contains&amp;#8221; a private object that is not itself finalizable, clearly you can refer to it from your own Finalize method without risk.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;In fact, a sophisticated developer might even create a cycle between two finalizable objects and coordinate their finalization behavior.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Consider a buffer and a file.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Finalize method of the buffer will flush any pending writes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Finalize method of the file will close the handle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Clearly it&amp;#8217;s important for the buffer flush to precede the handle close.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One legitimate but brittle solution is to create a cycle of references between the buffer and the file.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whichever Finalize method is called first will execute a protocol between the two objects to ensure that both side effects happen in order.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The subsequent Finalize call on the second object should do nothing.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;I should point out that Whidbey solves the buffer and file problem differently, relying on the semantics of critical finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I should also point out that any protocol for sequencing the finalization of two objects should anticipate that one day we may execute these two Finalize methods concurrently on two different threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, the protocol must be thread-safe.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Ordering&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;This raises the question of why finalization is unordered.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;In many cases, no natural order is even possible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Finalizable objects often occur in cycles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You could imagine decorating some references between objects, to indicate the direction in which finalization should proceed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would add a sorting cost to finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It would also cause complexity when these decorated references cross generation boundaries.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And in many cases the decorations would not fully eliminate cycles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is particularly true in component scenarios, where no single developer has sufficient global knowledge to create an ordering:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your component would achieve its guarantees when tested by you, prior to deployment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then in some customer application, additional decorated references would create cycles and your guarantees would be lost.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a recipe for support calls and appcompat issues.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Unordered finalization is substantially faster.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Not only do we avoid sorting (which might involve metadata access and marking through intermediate objects), but we can also efficiently manage the RegisteredForFinalization and ReadyToFinalize queues without ever having to memcpy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Finally, there&amp;#8217;s value in forcing developers to write Finalize methods with minimal dependencies on any other objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is key to our eventual goal of making Finalization scalable by distributing it over multiple threads.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Based on the above and other considerations like engineering complexity, we made a conscious decision that finalization should be unordered.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Partial Trust&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;There are no security permissions associated with the definition of a Finalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As we&amp;#8217;ve seen, it&amp;#8217;s possible to mount a denial of service attack via finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, many other denial of service attacks are possible from partial trust, so this is uninteresting.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Customers and partners sometimes ask why partially trusted code is allowed to participate in finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After all, Finalize methods are typically used to release unmanaged resources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Yet partially trusted code doesn&amp;#8217;t have direct access to unmanaged resources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It must always go through an API provided by an assembly with UnmanagedCodePermission or some other effective equivalent to FullTrust.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;The reason is that finalization can also be used to control pure managed resources, like object pools or caches.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I should point out that techniques based on weak handles can be more efficient than techniques based on finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Nevertheless, it&amp;#8217;s quite reasonable for partially trusted code to use finalization for pure managed resources.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;SQL Server has a set of constraints that they place on partially trusted assemblies that are loaded into their environment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I believe that these constraints prevent definition of static fields (except for initonly and literal static fields), use of synchronization, and the definition of Finalize methods.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, these constraints are not related to security.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rather, they are to improve scalability and reliability of applications by simplifying the threading model and by moving all shared state into the database where it can be transacted.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;It&amp;#8217;s hard to implement Finalize perfectly&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Even when all Finalize methods are authored by fully trusted developers, finalization poses some problems for processes with extreme availability requirements, like SQL Server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In part, this is because it&amp;#8217;s difficult to write a completely reliable Finalize method &amp;#8211; or a completely reliable anything else.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Here are some of the concerns specifically related to finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;ll explain later how some of these concerns are addressed in the context of a highly available process like SQL Server.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your Finalize method must tolerate partially constructed instances&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;It&amp;#8217;s possible for partially trusted code to subtype a fully trusted finalizable object (with APTCA) and throw an exception from the constructor.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This can be done before chaining to the base class constructor.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The result is that a zero-initialized object is registered for finalization.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Even if partially trusted code isn&amp;#8217;t intentionally causing finalization of your partially constructed instances, asynchronous problems like StackOverflowException, OutOfMemoryException or AppDomainUnloadException can cause your constructor to be interrupted at a fairly arbitrary location.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&lt;SPAN style="TEXT-DECORATION: none"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your Finalize method must consider the consequence of failure&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;It&amp;#8217;s possible for partially trusted code to subtype a fully trusted finalizable object (with APTCA) and fail to chain to the base Finalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This causes the fully trusted encapsulation of the resource to leak.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Even if partially trusted code isn&amp;#8217;t intentionally causing finalization of your object to fail, the aforementioned asynchronous exceptions can cause your Finalize method to be interrupted at a fairly arbitrary location.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;In addition, the CLR exposes a GC.SuppressFinalize method which can be used to prevent finalization of any object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Arguably we should have made this a protected method on Object or demanded a permission, to prevent abuse of this method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, we didn&amp;#8217;t want to add a member to Object for such an obscure feature.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we didn&amp;#8217;t want to add a demand, since this would have prevented efficient implementation of IDisposable from partial trust.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your object is callable after Finalization&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;We&amp;#8217;ve already seen how all the objects in a closure can access each other during finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, if any one of those objects re-establishes its reachability from a root (e.g. it places itself into a static field or a handle), then all the other objects it reaches will also become re-established.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is referred to as resurrection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you have a finalizable object that is publicly exposed, you cannot prevent your object from becoming resurrected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You are at the mercy of all the other objects in the graph.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;One possible solution here is to set a flag to indicate that your object has been finalized.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can pepper your entire API with checks to this flag, throwing an ObjectDisposedException if you are subsequently called.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Yuck.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your object is callable during Finalization&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;It&amp;#8217;s true that the finalizer thread is currently single-threaded (though this may well change in the future).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it&amp;#8217;s true that the finalizer thread will only process instances that &amp;#8211; at some point &amp;#8211; were discovered to be unreachable from the application.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, the possibility of resurrection means that your object may become visible to the application before its Finalize method is actually called.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that application threads and the finalizer thread can simultaneously be active in your object.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;If your finalizable object encapsulates a protected resource like an OS handle, you must carefully consider whether you are exposed to threading attacks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Shortly before we shipped V1, we fixed a number of handle recycling attacks that were due to race conditions between the application and Finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;See &lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx"&gt;&lt;SPAN style="COLOR: black"&gt;http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx&lt;/SPAN&gt;&lt;/A&gt; for more details.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your Finalizer could be called multiple times&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Just as there is a GC.SuppressFinalize method, we also expose a GC.ReRegisterForFinalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the same arguments about protected accessibility or security demands apply to the ReRegisterForFinalize method.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;U&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Your Finalizer runs in a delicate security context&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;As I&amp;#8217;ve explained in prior blogs, the CLR flows the compressed stack and other security information around async points like ThreadPool.QueueUserWorkItem or Control.BeginInvoke.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, in Whidbey we include more security information by default.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, we do not flow any security information from an object&amp;#8217;s constructor to an object&amp;#8217;s Finalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So (to use an absurd example) if you expose a fully trusted type that accepts a filename string in its constructor and subsequently opens that file in its Finalize method, you have created a security bug.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Clearly it&amp;#8217;s hard to write a correct Finalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the managed platform is supposed to make hard things easier.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;ll return to this when I discuss the new Whidbey features of SafeHandles, Critical Finalizers and Constrained Execution Regions.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;But what guarantees do I get if I don&amp;#8217;t use any of those new gizmos?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What happens in a V1 or V1.1 process?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;V1 &amp;amp; V1.1 Finalization Guarantees&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;If you allocate a finalizable object, we guarantee that it will be registered for finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once this has happened, there are several possibilities:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;1)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;As part of the natural sequence of garbage collection and finalization, the finalizer thread dequeues your object and finalizes it.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;2)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The process can terminate without cooperating with the CLR&amp;#8217;s shutdown code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This can happen if you call TerminateProcess or ExitProcess directly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In those cases, the CLR&amp;#8217;s first notification of the shutdown is via a DllMain DLL_PROCESS_DETACH notification.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is not safe to call managed code at that time, and we will leak all the finalizers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, the OS will do a fine job of reclaiming all its resources (including abandonment of any cross-process shared resources like Mutexes).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if you needed to flush some buffers to a file, your final writes have been lost.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;3)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The process can terminate in a manner that cooperates with the CLR&amp;#8217;s shutdown code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This includes calling exit() or returning from main() in any unmanaged code built with VC7 or later.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It includes System.Environment.Exit().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It includes a shutdown triggered from a managed EXE when all the foreground threads have completed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it includes shutdown of processes that are CLR-aware, like VisualStudio.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In these cases, the CLR attempts to drain both the ReadyToFinalize and the RegisteredForFinalization queues, processing all the finalizable objects.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;4)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The AppDomain containing your object is unloaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Prior to Whidbey, the AppDomain will not unload until we have scanned the ReadyToFinalize and the RegisteredForFinalization queues, processing all the finalizable objects that live in the doomed AppDomain.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;There are a few points to note here.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Objects are always finalized in the AppDomain they were created in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A special case exists for any finalizable objects that are agile with respect to AppDomains.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To my knowledge, the only such type that exists is System.Threading.Thread.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;I have heard that there is a bug in V1 and V1.1, where we get confused on AppDomain transitions in the ReadyToFinalize queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The finalization logic attempts to minimize AppDomain transitions by noticing natural partitions in the ReadyToFinalize queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;m told there is a bug where we may occasionally skip finalizing the first object of a partition.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I don&amp;#8217;t believe any customers have noticed this and it is fixed in Whidbey.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Astute readers will have noticed that during process shutdown and AppDomain unloading we actually finalize objects in the RegisteredForFinalization queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Such objects are still reachable and would not normally be subject to finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Normally a Finalize method can rely on safely accessing finalizable state that is rooted via statics or some other means.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can detect when this is no longer safe by checking AppDomain.IsFinalizingForUnload or Environment.HasShutdownStarted.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Since there is no ordering of finalization, critical infrastructure is being finalized along with application objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that WaitHandles, remoting infrastructure and even security infrastructure is disappearing underneath you.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a potential security concern and a definite reliability concern.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have spot-fixed a few cases of this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, we never finalize our Thread objects during process shutdown.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Finalization during process termination will eventually timeout.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a particular Finalize method gets stuck, or if the queue isn&amp;#8217;t reducing in size over time (i.e. you create 2 new finalizable instances out of each execution of your Finalize method), we will eventually timeout and terminate the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The exact timeouts depend on whether a profiler is attached and other details.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;The thread that initiates process shutdown performs the duties of &amp;#8220;watchdog.&amp;#8221;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is responsible for detecting timeouts during process termination.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If this thread is an STA thread, we cause it to pump COM calls in and out of the STA while it blocks as watchdog.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the application has a deadlock that implicates the STA thread while it is executing these unmanaged COM calls, then the timeout mechanism is defeated and the process will hang.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is fixed in Whidbey.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Subject to all of the above, we guarantee that we will dequeue your object and initiate a call to the Finalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We do not guarantee that your Finalize method can be JITted without running out of stack or memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We do not guarantee that the execution of your Finalize method will complete without being aborted.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We do not guarantee that any types you require can be loaded and have their .cctors run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All you get is a &amp;#8220;best effort&amp;#8221; attempt.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ll soon see how Whidbey extensions allow you to do better than this and guarantee full execution.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol"&gt;&amp;#183;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;(If you want to know more about the shutdown of managed processes, see &lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx"&gt;&lt;SPAN style="COLOR: black"&gt;http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx&lt;/SPAN&gt;&lt;/A&gt;.)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;SafeHandle&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Whidbey contains some mechanisms that address many of the V1 and V1.1 issues with finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let&amp;#8217;s start with SafeHandle, since it&amp;#8217;s the easiest to understand.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Conceptually, this is just an encapsulation of an OS handle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You should read the documentation of this feature for details.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Briefly, SafeHandle provides the following benefits:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;1)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Someone else wrote it and is maintaining it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Using it is much easier than building equivalent functionality yourself.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;2)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;It prevents races between an application thread and the finalizer thread in unmanaged code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it does this in a manner that leverages the type system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Specifically, clients are forced to deal with SafeHandles rather than IntPtrs or value types which don&amp;#8217;t have strong identity and lifetime semantics.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;3)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;It prevents handle-recycling attacks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can read more details about finalization races (#2 above) and this bullet on handle-recycling attacks by reading &lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx"&gt;&lt;SPAN style="COLOR: black"&gt;http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx&lt;/SPAN&gt;&lt;/A&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that blog from last April, I allude to the existence of SafeHandle without giving details.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;4)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;It discourages promotion of large graphs of objects, by placing the finalizable resources in a tiny leaf instance.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;5)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;It participates with the PInvoke marshaler to ensure that unmarshaled instances will be registered for finalization.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;6)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;For the handful of bizarre APIs that aren&amp;#8217;t covered by our standard marshaling styles, Constrained Execution Regions (CERs) can be used to guarantee that unmarshaled instances will be registered for finalization.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;7)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;It uses the new Critical Finalization mechanism to guarantee that leaks cannot occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that we not only guarantee we will initiate execution of your Finalize method, but we also make some strong guarantees that allow you to ensure that it actually completes execution.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;8)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;In order to guarantee that there will be no leaks, we necessarily leave the system open to denial of service and hangs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the halting problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Critical Finalization mechanism addresses this dilemma by making the leak protection explicit, restricting it to small regions of carefully written code, and by using the security system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Only trusted code can achieve strong guarantees about leakage.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Such code is trusted not to create denial of service problems, whether maliciously or inadvertently, over small blocks of explicitly identified code.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;9)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Since SafeHandle uses Critical Finalization, it solves the problem of sequencing buffer flushing before handle closing that I mentioned earlier.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;So what is this Critical Finalization thing?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Critical Finalization (CF) and CERs&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Any object that derives from CriticalFinalizerObject (including SafeHandle) obtains critical finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;1)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Before any objects of this type are created, the CLR will &amp;#8220;prepare&amp;#8221; any resources that will be necessary for the Finalize method to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Preparation includes JITting the code, running class constructors and &amp;#8211; most importantly &amp;#8211; traversing the static reachability of other methods and types that will be required during execution and making sure that they are likewise prepared.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, the CLR cannot statically traverse through indirections like interface calls and virtual calls.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So there is a mechanism for the developer to guide the CLR through these opaque indirections.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;2)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The CLR will never timeout on the execution of one of these Finalize methods.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As I mentioned, we rely on the limited amount of code written via this discipline combined with the trust decisions of the security system to avoid hangs here.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;3)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;When the Finalize method is called, it is called in a protected state that prevents the CLR from injecting Thread.Aborts or other optional asynchronous exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Because of our special preparation, we also prevent other asynchronous exceptions like OutOfMemoryExceptions due to JITting or type loading and TypeInitializationExceptions due to .cctors failures.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, if the application tries to allocate an object it may get an OutOfMemoryException.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is application-induced rather than system-induced and therefore is not considered the CLR&amp;#8217;s responsibility.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Finalize method can use standard exception handling to protect itself here.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;4)&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;All normal finalizable objects are either executed or discarded without finalization, before any critical finalizers are executed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that a buffer flush can precede the close of the underlying handle.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;The first 3 bullet points above are not restricted to CF.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These bullet points apply to all CERs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The fundamental difference between CF and other CERs is the funky flow control from the instantiation of an object to the execution of its Finalize method via registration on our finalization queues.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Other CERs can use normal block scopes in a single method to express the same reliability concepts.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For normal CERs, the preparation phase, the forward execution phase and the backout phases are all contained in a single method.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;A full description of CERs is beyond the scope of a note that is ostensibly about finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, a brief description makes sense.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Essentially, CERs address issues with asynchronous exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I have already mentioned asynchronous exceptions, which is the CLR&amp;#8217;s term for all the pesky problems that manifest themselves as surprising exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These are distinct from the application-level exceptions, which presumably are anticipated by and handled by the application.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;You can read about asynchronous exceptions and the novel problems introduced by a managed execution environment that virtualizes resources so aggressively at &lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/06/23/51482.aspx"&gt;&lt;SPAN style="COLOR: black"&gt;http://blogs.msdn.com/cbrumme/archive/2003/06/23/51482.aspx&lt;/SPAN&gt;&lt;/A&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;In V1 and V1.1, the CLR does a poor job of distinguishing asynchronous exceptions from application exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Whidbey, we are starting to make this separation but it remains one of the weak design points for our hosting and exception stories.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Anyway, I&amp;#8217;m sure that many readers are familiar with the difficulty of writing reliable &lt;B&gt;&lt;I&gt;unmanaged&lt;/I&gt;&lt;/B&gt; code that is guaranteed to complete in the face of limited resources (e.g. memory or stack), free threading, and other facts of life.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And by now, if you&amp;#8217;ve read all the blog articles I&amp;#8217;ve mentioned, you are also familiar with the additional problems caused by a highly virtualized execution environment.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;CERs allow you to declare regions of code where the CLR is constrained from injecting any system-generated errors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the author of the code is constrained from performing certain actions if he wants to avoid additional exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;An obvious example is that he shouldn&amp;#8217;t new up an object if he is not prepared to deal with an OutOfMemoryException from that operation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;In addition to CERs, Whidbey provides reliability contracts.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These contracts can be used to annotate methods with their guarantees and requirements with respect to reliability.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Using these contracts, it&amp;#8217;s possible to compose reliable execution out of components written by different authors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is necessary for building reliable applications that make use of framework services.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the reliability requirements and guarantees of the framework services were not themselves explicit, the client applications could not remain reliable on top of them.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Finalization in SQL Server and other high availability hosts&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;Back to finalization.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;In a normal unhosted process, there isn&amp;#8217;t a strong distinction between normal and critical finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Normal processes won&amp;#8217;t run out of memory, and if they do they should probably Fail Fast.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s unlikely that the risk of trying to continue execution after resource exhaustion is worth the increased risk of subsequent crashes, hangs or other corruptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Normal processes won&amp;#8217;t experience Thread.Aborts that are injected across threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(As opposed to aborting the current thread, which is no more dangerous than throwing any other exception).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;So the only real concern is whether all the finalizable objects will drain during process exit, before the timeouts kick in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The timeouts are quite generous and in practice this is not a concern.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;However, a hosted process like SQL Server is quite different.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Because of SQL Server&amp;#8217;s availability requirements, it is vital that the process not FailFast for something innocuous like OutOfMemoryExceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, SQL Server tries to run on the brink of memory exhaustion for performance reasons, so these memory exceptions are a constant fact of life in that environment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Furthermore, SQL Server uses Thread.Abort explicitly across threads to terminate long-running requests and it uses Thread.Abort implicitly to unload AppDomains.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On a heavily loaded system, AppDomains may be unloaded to relieve resource pressure.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;I have a lengthy blog on this topic, but I have not been able to post it because it talks about undisclosed Whidbey features.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At some point (no later than shipping Beta1), you will find it at &lt;A href="http://blogs.msdn.com/cbrumme"&gt;&lt;SPAN style="COLOR: black"&gt;http://blogs.msdn.com/cbrumme&lt;/SPAN&gt;&lt;/A&gt; with a title of Hosting.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Until then, I&amp;#8217;ll just mention that the Whidbey APIs support an escalation policy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a declarative mechanism by which the host can express timeouts for normal finalization, normal AppDomain unload, normal Abort attempts, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In addition to timeouts, the escalation policy can indicate appropriate actions whenever these timeouts expire.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So a normal AppDomain unload could (for example) be escalated to a rude AppDomain unload or a normal process exit or a rude process exit.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;The distinction between polite/normal and rude involves several aspects beyond finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we just consider finalization, polite/normal means that we execute both normal and critical finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Contrast this with a rude scenario where we will ignore the normal finalizers, which are discarded, and only execute the critical finalizers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As you might expect, a similar distinction occurs between executing normal exception backout on threads, vs. restricting ourselves to any backout that is associated with CERs.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: black; mso-bidi-font-family: Tahoma"&gt;This allows a host to avoid solving the halting problem when performing normal finalization and exception backout, without putting the process at risk with respect to (critical) resource leakage or inconsistent state.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="COLOR: black"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=77460" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item><item><title>Apartments and Pumping in the CLR</title><link>http://blogs.msdn.com/b/cbrumme/archive/2004/02/02/66219.aspx</link><pubDate>Mon, 02 Feb 2004 19:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:66219</guid><dc:creator>cbrumme</dc:creator><slash:comments>65</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=66219</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2004/02/02/66219.aspx#comments</comments><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I&amp;#8217;ve already written the much-delayed blog on Hosting, but I can&amp;#8217;t post it yet because it mentions a couple of new Whidbey features, which weren&amp;#8217;t present in the PDC bits.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously Microsoft doesn&amp;#8217;t want to make product disclosures through my random blog articles.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I&amp;#8217;m hoping this will be sorted out in another week or two.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;While we&amp;#8217;re waiting, I thought I would talk briefly(!) about pumping and apartments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR made some fundamental decisions about OLE, thread affinity, reentrancy and finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These decisions have a significant impact on program correctness, server scalability, and compatibility with legacy (i.e. unmanaged) code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So this is going to be a blog like the one on Shutdown from last August (see &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There will be more detail than you probably care to know about one of the more frustrating parts of the Microsoft software stack.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;First, an explanation of my odd choice of terms.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;m using OLE as an umbrella which includes the following pieces of technology:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;COM &amp;#8211; the fundamental object model, like IUnknown and IClassFactory&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;DCOM &amp;#8211; remoting of COM using IDL, NDR pickling and the SCM&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN lang=FR style="mso-ansi-language: FR"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Automation &amp;#8211; IDispatch, VARIANT, Type Libraries, etc.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Active/X &amp;#8211; Protocols for controls and their containers&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Next, some disclaimers:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I am not and have never been a GUI programmer.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So anything I know about Windows messages and pumping is from debugging GUI applications, not from writing them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;m not going to talk about WM_PENCTL notifications or anything else that requires UI knowledge.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Also, I&amp;#8217;m going to point out a number of problems with OLE and apartments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The history of the CLR and OLE are closely related.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, at one point COM+ 1.0 was known internally as COM98 and the CLR was known internally as COM99.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We had some pretty aggressive ship targets back then!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In general, I love OLE and the folks who work on it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Although it is inappropriate for the Internet, DCOM is still the fastest and most enterprise-ready distributed object system out there.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a few ways the architecture of .NET Remoting is superior to DCOM, but we never had the time or resources to even approach the engineering effort that has gone into DCOM.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Presumably Indigo will eventually change this situation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I also love COM&amp;#8217;s strict separation of contract from implementation, the ability to negotiate for contracts, and so much more.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The bottom line is that OLE has had at least as much impact on Microsoft products and the industry, in its day, as .NET is having now.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But, like anything else, OLE has some flaws.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In contrast to the stark architectural beauty of COM and DCOM, late-bound Automation is messy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At the time this was all rolled out to the world, I was at Borland and then Oracle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As an outsider, it was hard for me to understand how one team could have produced such a strange combination.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of course, Automation has been immensely successful &amp;#8211; more successful than COM and DCOM.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;My aesthetic taste is clearly no predictor of what people want.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Generally, people want whatever gets the job done, even if it does so in an ad hoc way.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And Automation has enabled an incredible number of application scenarios.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Apartments&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If there&amp;#8217;s another part of OLE that I dislike, it&amp;#8217;s Single Threaded Apartments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Presumably everyone knows that OLE offers three kinds of apartments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;U&gt;Single Threaded Apartment (STA)&lt;/U&gt; &amp;#8211; one affinitized thread is used to call all the objects residing in the apartment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any call on these objects from other threads must perform cross-thread marshaling to this affinitized thread, which dispatches the call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Although a process can have an arbitrary number of STAs (with a corresponding number of threads), most client processes have a single Main STA and the GUI thread is the affinitized thread that owns it.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;U&gt;Multiple Threaded Apartment (MTA)&lt;/U&gt; &amp;#8211; each process has at most one MTA at a time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the current MTA is not being used, OLE may tear it down.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A different MTA will be created as necessary later.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most people think of the MTA as not having thread affinity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But strictly speaking it has affinity to a group of threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This group is the set of all the threads that are not affinitized to STAs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some of the threads in this group are explicitly placed in the MTA by calling CoInitializeEx.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Other threads in this group are implicitly in the MTA because the MTA exists and because these threads haven&amp;#8217;t been explicitly placed into STAs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So, by the strict rules of OLE, it is not legal for STA threads to call on any objects in the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, such calls must be marshaled from the calling STA thread over to one of the threads in the MTA before the call can legally proceed.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;U&gt;Neutral Apartment (NA)&lt;/U&gt; &amp;#8211; this is a recent invention (Win2000, I think).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There is one NA in the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Objects contained in the NA can be called from any thread in the process (STA or MTA threads).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are no threads associated with the NA, which is why it isn&amp;#8217;t called NTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Calls into NA objects can be relatively efficient because no thread marshaling is ever required.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, these cross-apartment calls still require a proxy to handle the transition between apartments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Calls from an object in the NA to an object in an STA or the MTA might require thread marshaling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This depends on whether or not the current thread is suitable for calling into the target object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, a call from an STA object to an NA object and from there to an MTA object will require thread marshaling during the transition out of the NA into the MTA.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Threading&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The MTA is effectively a free-threaded model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(It&amp;#8217;s not quite a free-threaded model, because STA threads aren&amp;#8217;t strictly allowed to call on MTA objects directly).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;From an efficiency point of view, it is the best threading model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Also, it imposes the least semantics on the application, which is also desirable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The main drawback with the MTA is that humans can&amp;#8217;t reliably write free-threaded code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Well, a few developers can write this kind of code if you pay them lots of money and you don&amp;#8217;t ask them to write very much.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if you code review it very carefully.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And you test it with thousands of machine hours, under very stressful conditions, on high-end MP machines like 8-ways and up.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And you&amp;#8217;re still prepared to chase down a few embarrassing race conditions once you&amp;#8217;ve shipped your product.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But it&amp;#8217;s not a good plan for the rest of us.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The NA model is truly free-threaded, in the sense that any thread in the process can call on these objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All such threads must still transition through a proxy layer that maintains the apartment boundary.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But within the NA all calls are direct and free-threaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the only apartment that doesn&amp;#8217;t involve thread affinity.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Although the NA is free-threaded, it is often used in conjunction with a lock to achieve rental threading.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The rental model says that only one thread at a time can be active inside an object or a group of objects, but there is no restriction on which thread this might be.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is efficient because it avoids thread marshaling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rather than marshaling a call from one thread to whatever thread is affinitized to the target objects, the calling thread simply acquires the lock (to rent the context) and then completes the call on the current thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the thread returns back out of the context, it releases the lock and now other threads can make calls.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you call out of a rental context into some other object (as opposed to the return pathway), you have a choice.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can keep holding the lock, in which case other threads cannot rent the context until you fully unwind.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this mode, the rental context supports recursion of the current thread, but it does not support reentrancy from other threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Alternatively, the thread could release the lock when it calls out of the rental context, in which case it must reacquire the lock when it unwinds back and returns to the rental context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this mode, the rental context supports full reentrancy.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Throughout this blog, we&amp;#8217;ll be returning to this fundamental decision of whether to support reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s a complex issue.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If only recursion is supported on a rental model, it&amp;#8217;s clear that this is a much more forgiving world for developers than a free-threaded model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once a thread has acquired the rental lock, no other threads can be active in the rented objects until the lock has been released.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the lock will not be released until the thread fully unwinds from the call into the context.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Even with reentrancy, the number of places where concurrency can occur is limited.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unless the renting thread calls out of the context, the lock won&amp;#8217;t be released and the developer knows that other threads aren&amp;#8217;t active within the rented objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, it might be hard for the developer to know all the places that call out of the current context, releasing the lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Particularly in a componentized world, or a world that combines application code with frameworks code, the developer can rarely have sufficient global knowledge.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So it sounds like limiting a rental context to same-thread recursion is better than allowing reentrancy during call outs, because the developer doesn&amp;#8217;t have to worry about other threads mutating the state of objects in the rental context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is true.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it also means that the resulting application is subject to more deadlocks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Imagine what can happen if two rental contexts are simultaneously making calls to each other.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thread T1 holds the lock to rent context C1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thread T2 holds the lock to rent context C2.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If T1 calls into C2 just as T2 calls into C1, and we are on the recursion plan, we have a classic deadlock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Two locks have been taken in different sequences by two different threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Alternatively, if we are on a reentrancy plan, T1 will release the lock for C1 before contending for the lock on C2.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And T2 will release the lock for C2 before contending for the lock on C1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The deadlock has been avoided, but T1 will find that the objects in C1 have been modified when it returns.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And T2 will find similar surprises when it returns to C2.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Affinity&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, we now understand the free-threaded model of the MTA and NA and we understand how to build a rental model on top of these via a lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;How about the single-threaded affinitized model of STAs?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s hard to completely describe the semantics of an STA, because the complete description must incorporate the details of pages of OLE pumping code, the behavior of 3&lt;SUP&gt;rd&lt;/SUP&gt; party IMessageFilters, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But generally an STA can be thought of as an &lt;B style="mso-bidi-font-weight: normal"&gt;affinitized rental context&lt;/B&gt; with &lt;B style="mso-bidi-font-weight: normal"&gt;reentrancy&lt;/B&gt; and &lt;B style="mso-bidi-font-weight: normal"&gt;strict stacking&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By this I mean:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l4 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;It is &lt;B style="mso-bidi-font-weight: normal"&gt;affinitized rental&lt;/B&gt; because all calls into the STA must marshal to the correct thread and because only one logical call can be active in the objects of the apartment at any time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(This is necessarily the case, since there is only ever one thread).&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l4 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;It has &lt;B style="mso-bidi-font-weight: normal"&gt;reentrancy&lt;/B&gt; because every callout from the STA thread effectively releases the lock held by the logical caller and allows other logical callers to either enter or return back to the STA.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l4 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;It has &lt;B style="mso-bidi-font-weight: normal"&gt;strict stacking&lt;/B&gt; because one stack (the stack of the affinitized STA thread) is used to process all the logical calls that occur in the STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When these logical calls perform a callout, the STA thread reentrantly picks up another call in, and this pushes the STA stack deeper.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the first callout wants to return to the STA, it must wait for the STA thread&amp;#8217;s stack to pop all the way back to the point of its own callout.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;That point about strict stacking is a key difference between true rental and the affinitized rental model of an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With true rental, we never marshal calls between threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since each call occurs on its own thread, the pieces of stack for different logical threads are never mingled on an affinitized thread&amp;#8217;s actual stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Returns back into the rental context after a callout can be processed in any order.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Returns back into an STA after a callout must be processed in a highly constrained order.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We&amp;#8217;ve already seen a number of problems with STAs due to thread affinity, and we can add some more.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here&amp;#8217;s the combined list:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l5 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;Marshaling calls between threads is expensive, compared to taking a lock.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=2&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l5 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;Processing returns from callouts in a constrained fashion can lead to inefficiencies.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, if the topmost return isn&amp;#8217;t ready for processing yet, should the affinitized thread favor picking up a new incoming call (possibly leading to unconstrained stack growth) or should it favor waiting for the topmost return to complete (possibly idling the affinitized thread completely and conceivably resulting in deadlocks).&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=3&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l5 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;Any conventional locks held by an affinitized thread are worthless.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The affinitized thread is processing an arbitrary number of logical calls, but a conventional lock (like an OS CRITICAL_SECTION or managed Monitor) will not distinguish between these logical calls.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, all lock acquisitions are performed by the single affinitized thread and are granted immediately as recursive acquisitions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you are thinking of building a more sophisticated lock that avoids this issue, realize that you are making that classic reentrancy vs. deadlock decision all over again.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=4&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l5 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;Imagine a common server situation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The first call comes in from a particular client, creates a few objects (e.g. a shopping cart) and returns.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Subsequent calls from that client manipulate that initial set of objects (e.g. putting some items into the shopping cart).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A final call checks out the shopping cart, places the order, and all the objects are garbage collected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now imagine that all those objects are affinitized to a particular thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As a consequence, the dispatch logic of your server must ensure that all calls from the same client are routed to the same thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if that thread is busy doing other work, the dispatch logic must delay processing the new request until the appropriate affinitized thread is available.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is complicated and it has a severe impact on scalability.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=5&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l5 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;STAs must pump.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(How did I get this far without mentioning pumping?)&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=6&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l5 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;Any STA code that assumed a single-threaded world for the process, rather than just for the apartment, might not pump.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Such code breaks when we introduce the CLR into the process, as we will see.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Failure to Pump&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Let&amp;#8217;s look at those last two bullet points in more detail.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When your STA thread is doing nothing else, it needs to be checking to see if any other threads want to marshal some calls into it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is done with a Windows message pump.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the STA thread fails to pump, these incoming calls will be blocked.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the incoming calls are GUI SendMessages or PostMessages (which I think of as synchronous or asynchronous calls respectively), then failure to pump will produce an unresponsive UI.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the incoming calls are COM calls, then failure to pump will result in calls timing out or deadlocking.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If processing one incoming call is going to take a while, it may be necessary to break up that processing with intermittent visits to the message pump.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, if you pump you are allowing reentrancy to occur at those points.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So the developer loses all his wonderful guarantees of single threading.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Unfortunately, there&amp;#8217;s a whole lot of STA code out there which doesn&amp;#8217;t pump adequately.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For the most part, we see this in non-GUI applications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you have a GUI application that isn&amp;#8217;t pumping enough, it&amp;#8217;s obvious right there on the screen.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Those bugs tend to get fixed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For non-GUI applications, a failure to pump may not be noticed in unmanaged code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When that code is moved to managed (perhaps by re-compiling some VB6 code as VB.NET), we start seeing bugs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let&amp;#8217;s look at a couple of real-world cases that we encountered during V1 of the CLR and how the lingering effects of these cases are still causing major headaches for managed developers and for Microsoft Support.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;ll describe a server case first, and then a client case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;ADO&lt;/B&gt;&lt;/st1:place&gt;&lt;/st1:City&gt;&lt;B style="mso-bidi-font-weight: normal"&gt; and ASP Compatibility Mode&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;ADO.NET and ASP.NET are a winning combination.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But ASP.NET also supports an ASP compatibility mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this mode, legacy ASP pages can be served up by the managed ASP.NET pipeline.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Such pages were written before we invented our managed platform, so they use &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; rather than ADO.NET for any data access.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Also, in this mode the DCOM threadpool is used rather than the managed System.Threading.ThreadPool.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Although all the threads in the managed ThreadPool are explicitly placed in the MTA (as you might hope and expect), the DCOM threadpool actually contains STA threads.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The purpose of this STA threadpool was to allow legacy STA COM objects in general, and VB6 objects in particular, to be moved from the client to the server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The result suffers from the scaling problems I alluded to before, since requests are dispatched on up to 100 STA threads with careful respect for any affinity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Also, VB6 has a variable scope which corresponds to &amp;#8220;global&amp;#8221; (I forget its name), but which is treated as per-thread when running on the server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If there are more than 100 clients using a server, multiple clients will share a single STA thread based on the whims of the request dispatch logic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that global variables are shared between sets of clients in a surprising fashion, based on the STA that they happen to correspond to.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;A typical ASP page written in VBScript would establish a (hopefully pooled) database connection from &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt;, query up a row, modify a field, and write the row back to the database.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since the page was likely written in VB, any COM AddRef and Release calls on the &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; row and field value objects were supplied through the magic of the VB6 runtime.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means they occur on the same thread and in a very deterministic fashion.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The ASP page contains no explicit pumping code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, at no point was the STA actually pumped.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Although this is a strict violation of the rules, it didn&amp;#8217;t cause any problems.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because there are no GUI messages or inter-apartment COM calls that need to be serviced.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This technique of executing ASP pages on STAs with &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; worked fairly well &amp;#8211; until we tried to extend the model to ASP.NET running in ASP compatibility mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The first problem that we ran into was that all managed applications are automatically multi-threaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For any application of reasonable complexity, there are sure to be at least a few finalizable objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These objects will have their Finalize methods called by one or more dedicated finalizer threads that are distinct from the application threads.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;(It&amp;#8217;s important that finalization occurs on non-application threads, since we don&amp;#8217;t want to be holding any application locks when we call the Finalize method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And today the CLR only has a single Finalizer thread, but this is an implementation detail.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s quite likely that in the future we will concurrently call Finalize methods on many objects, perhaps by moving finalization duties over to the ThreadPool.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would address some scalability concerns with finalization, and would also allow us to make stronger guarantees about the availability of the finalization service).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Our COM Interop layer ensures that we almost only ever call COM objects in the correct apartment and context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The one place where we violate COM rules is when the COM object&amp;#8217;s apartment or context has been torn down.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that case, we will still call IUnknown::Release on the pUnk to try to recover its resources, even though this is strictly illegal.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We&amp;#8217;ve gone backwards and forwards on whether this is appropriate, and we provide a Customer Debug Probe so that you can detect whether this is happening in your application.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, let&amp;#8217;s pretend that we absolutely always call the pUnk in the correct apartment and context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of an object living in an STA, this means that the Finalizer thread will marshal the call to the affinitized thread of that STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if that STA thread is not pumping, the Finalizer thread will block indefinitely while attempting to perform the cross-thread marshaling.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The effect on a server is crippling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Finalizer thread makes no progress.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The number of unreleased pUnks grows without bounds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Eventually some resource (usually memory) is exceeded and the process crashes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One solution is to edit the original ASP page to pump the underlying STA thread that it is executing on.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A light-weight way to pump is to call Thread.CurrentThread.Join(0).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This causes the current thread to block until the current thread dies (which isn&amp;#8217;t going to happen) or until 0 milliseconds have elapsed &amp;#8211; whichever happens first.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;ll explain later why this also performs &lt;I style="mso-bidi-font-style: normal"&gt;some&lt;/I&gt; pumping and why this is a controversial aspect of the CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A heavier-weight way to pump is to call GC.WaitForPendingFinalizers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This not only performs pumping, but it also waits for the Finalization queue to drain.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you are porting a page that produces a modest number of COM objects, doing a simple Join on each page may be sufficient.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If your page performs elaborate processing, perhaps creating an unbounded number of COM objects in a loop, then you may need to either add a Join within the loop or WaitForPendingFinalizers at the end of the page processing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The only way to really know is to experiment with both techniques, measuring the growth of the Finalization queue and the impact on server throughput.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;ADO&amp;#8217;s Threading Model&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There was another problem with using &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; from ASP.NET&amp;#8217;s ASP compatibility mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Do you know what the threading model of &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; is?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, if you check the registry for some ADO CLSIDs on your machine, you may find them registered as ThreadingModel=Single or you may find them registered as ThreadingModel=Both.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If these classes are registered as Single, OLE will carefully ensure that their instances can only be called from the thread that they were created on.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This implies that the objects can assume a single-threaded view of the world and they do not need to be written in a thread-safe manner.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If these classes are registered as Both, OLE will ensure that their instances are only called from threads in the right apartment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if that apartment is the MTA, these objects better have been written in a thread-safe manner.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, they had better be using InterlockedIncrement and Decrement, or an equivalent, for reference counting.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Unfortunately, the &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; classes are not thread-safe.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Strictly speaking, they should never be registered as anything but Single.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You may find them registered as Both on your machine because this improves scalability and throughput for some key scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And those key scenarios happen to limit themselves to &amp;#8220;one thread at a time&amp;#8221; because of how ASP and VB6 work.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In fact, the legacy &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; classes don&amp;#8217;t even support single-threaded access if there is reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They will randomly crash when used in this manner (and this is exactly the manner in which &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; was driven in the early days of V1).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here are the steps:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The page queries up an &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; row object, which enters managed code via COM Interop as an RCW (runtime-callable wrapper).&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;By making a COM call on this RCW, the page navigates to a field value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This field value also enters managed code via COM Interop as an RCW.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The page now makes a COM call via &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; which results in a call out to the remote database.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At this point, the STA thread is pumped by the DCOM remote call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since this is a remote call, it&amp;#8217;s going to take a while before it returns.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The garbage collector decides that it&amp;#8217;s time to collect.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At this point, the RCW for the field value is still reachable and is reported.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The RCW for the row object is no longer referenced by managed code and is collected.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The Finalizer thread notices that the pUnk underlying the row&amp;#8217;s RCW is no longer in use, and it makes the cross-apartment call from the Finalizer thread&amp;#8217;s apartment (MTA) to the &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; row object&amp;#8217;s apartment (STA).&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;Recall that the STA thread is pumping for the duration of the remote database call (#3 above).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It picks up the cross-thread call from the Finalizer (#5 above) and performs the Release on the Row object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the final Release and &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; deletes the unmanaged Row object from memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This logical call unwinds and the Finalizer thread is unblocked (hurray).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The STA thread returns to pumping.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The remote database call returns back to the server machine.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The STA thread picks it up from its pumping loop and returns back to the page, unwinding the thread.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The page now updates the field value, which involves a COM call to the underlying &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; object.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo3; tab-stops: list .5in"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; crashes or randomly corrupts memory.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;What happened?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; developers made a questionable design decision when they implemented COM reference counting throughout their hierarchy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The field values refer to their owning row object, but they don&amp;#8217;t hold a reference count on that row.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, they assume that the row will live as long as all of its associated field values.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And yet, whenever the application makes an &lt;st1:place w:st="on"&gt;&lt;st1:City w:st="on"&gt;ADO&lt;/st1:City&gt;&lt;/st1:place&gt; call on a field value, the field value will access that (hopefully present) row.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This assumption worked fine in the days of ASP and VB6.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So nobody even noticed the bug until the CLR violated those threading assumptions &amp;#8211; without violating the underlying OLE rules, of course.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;It was impractical to fix this by opening up &lt;st1:place w:st="on"&gt;&lt;st1:City w:st="on"&gt;ADO&lt;/st1:City&gt;&lt;/st1:place&gt; and rewriting the code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are many different versions of &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; in existence, and many products that distribute it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Another option was to add GC.KeepAlive(row) calls at the bottom of each page, to extend the lifetime of the row objects until the field values were no longer needed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would have been a nightmare for Support.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Instead, the &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; team solved the problem for managed code with a very elegant technique.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(I invented it, so of course I think it was elegant).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They opened up the assembly that was created by TlbImp&amp;#8217;ing ADO.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then they added managed references from the RCWs of the field values to the RCWs of their owning rows.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These managed references are completely visible to the garbage collector.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now the GC knows that if the field values are reachable then the row values must also be reachable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Problem solved.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;No Typelib Registered&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Incidentally, we ran into another very common problem when we moved existing client or server COM applications over to managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whenever an application uses a COM object, it tries hard to match the thread of the client to the ThreadingModel of the server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, if the application needs to use a ThreadingModel=Main COM object, the application tries to ensure that the creating thread is in an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Similarly, if the application needs to use a ThreadingModel=Free COM object, it tries to create this object from an MTA thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if a COM object is ThreadingModel=Both, the application will try to access the object from the same sort of thread (STA vs. MTA) as the thread that created the object.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One reason for doing this is performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you can avoid an apartment transition, your calls will be much faster.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Another reason has to do with pumping and reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you make a cross-apartment call into an STA, the STA better be pumping to pick up your call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if you make a cross-apartment call out of an STA, your thread will start pumping and your application becomes reentrant.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a small dose of free-threading, and many application assumptions start to break.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A final reason for avoiding apartment transitions is that they often aren&amp;#8217;t supported.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, most ActiveX scenarios require that the container and the control are in the same STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you introduce an apartment boundary (even between two STAs), bizarre cases like Input Synchronous messages stop working properly.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The net result is that a great many applications avoid using COM objects across apartment boundaries.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And this means that &amp;#8211; even if that COM object is nominally marshalable across an apartment boundary &amp;#8211; this often isn&amp;#8217;t being tested.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So an application might install itself without ensuring that the typelib of the COM component is actually registered.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When the application is moved to managed code, developers are frustrated to see InvalidCastExceptions on the managed side.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A typical sequence is that they successfully &amp;#8216;new&amp;#8217; the COM object, implying that the CoCreate returned a pUnk which was wrapped in an RCW.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then when they cast it to one of the interfaces that they know is supported, a casting exception is thrown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This casting exception is due to a QueryInterface call failing with E_NOINTERFACE.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Yet this HRESULT is not returned by the COM object, which does indeed support the interface.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, it is returned by a COM apartment proxy which sits between the RCW and that COM object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The COM apartment proxy is simply failing to marshal the interface across the apartment boundary &amp;#8211; usually because the COM object is using the OLEAUT marshaler and the Typelib has not been properly registered.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is a common failure, and it&amp;#8217;s unfortunate that a generic E_NOINTERFACE doesn&amp;#8217;t lead to better debuggability for this case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Finally, I can&amp;#8217;t help but mention that the COM Interop layer added other perturbations to many unmanaged COM scenarios that seemed to be working just fine.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Common perturbations from managed code include garbage collection, a Finalizer thread, strict conformance to OLE marshaling rules, and the fact that managed objects are agile with respect to COM apartments and COM+ contexts (unless they derive from ServicedComponent).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For instance, Trident required that all calls on its objects occur on the correct thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But Trident also had an extension model where 3&lt;SUP&gt;rd&lt;/SUP&gt; party objects could be aggregated onto their base objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, the aggregator performed blind delegation to the 3&lt;SUP&gt;rd&lt;/SUP&gt; party objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And &amp;#8211; even more unfortunate &amp;#8211; this blind delegation did not exclude QI&amp;#8217;s for IMarshal.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, managed objects implement IMarshal to achieve their apartment and context agility.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So if Trident aggregated a managed object as an extention, the containing Trident object would attempt to become partially agile in a very broken way.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Hopefully we found and dealt with most of these issues before we shipped V1.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Not Pumping a Client&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I said I would describe two cases where non-pumping unmanaged code caused problems when we moved to managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The above explains, in great detail, how &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;ADO&lt;/st1:place&gt;&lt;/st1:City&gt; and ASP compatibility mode caused us problems on the server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now let&amp;#8217;s look at the non-GUI client case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We all know that a WinForms GUI client is going to put the main GUI thread into an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we know that there&amp;#8217;s a lot of pumping in a GUI application, or else not much is going to show on the screen.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Assume for a moment that a Console application also puts its main thread into an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that main thread creates any COM objects via COM Interop, and if those COM objects are ThreadingModel=&lt;st1:place w:st="on"&gt;Main&lt;/st1:place&gt; or Both, then the application better be pumping.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If it fails to pump, we&amp;#8217;ll have exactly the same situation with our server running ASP compatibility mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Finalizer thread won&amp;#8217;t be able to marshal calls into the STA to Release any pUnks.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;On a well-loaded server, that failure is quickly noticed by the developer or by the folks in operations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But on a client, this might be just a mild case of constipation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The rate of creation of finalizable objects may be low enough that the problem is never noticed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it may be noticed as a gradual build up of resources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the problem is reported to Microsoft Support, the customer generally categorizes it as a garbage collection bug.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So what is the apartment of a Console application&amp;#8217;s main thread?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, it depends.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you build a Console application in Notepad, the main thread is likely to start off in the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you build a Console application with Visual Studio, then if you pick C# or VB.NET your main thread is likely to be in an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you build a Console application with Visual Studio and you choose managed C++, your main thread is likely to be in an MTA for V1 or V1.1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I think it&amp;#8217;s likely to be in an STA for our next release.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Wow.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Why are we all over the place on this?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Mostly, it&amp;#8217;s because there is no correct answer.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Either the developer is not going to use any COM objects in his Console application, in which case the choice doesn&amp;#8217;t really matter, or the developer is going to use some COM objects and this should inform his decision.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For instance, if the developer will use COM objects with ThreadingModel=&lt;st1:place w:st="on"&gt;Main&lt;/st1:place&gt;, he probably wants to put his main thread into an STA so he can use the COM objects directly without cross-thread marshaling and all the issues that this would imply.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means he should also pump that thread, if there are other threads (like the Finalizer!) active in the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Alternatively, if the developer intends to use COM objects with ThreadingModel=Free, he probably wants to put his main thread in the MTA so he can access those objects directly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now he doesn&amp;#8217;t need to pump, but he does need to consider the implications of writing free-threaded code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Either way, the developer has some responsibility.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Unfortunately, the choice of a default is typically made by the project type that he selects in Visual Studio, or is based on the CLR&amp;#8217;s default behavior (which favors MTA).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And realistically the subtleties of apartments and pumping are beyond the knowledge (or interest) of most managed developers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let&amp;#8217;s face it: nobody should have to worry about this sort of thing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;The Managed CoInitialize Mess&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There are three ways to select an apartment choice for the main thread of your Console application.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All three of these techniques have concerns associated with them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l2 level1 lfo4; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;You can place either an STAThreadAttribute or MTAThreadAttribute onto the main method.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l2 level1 lfo4; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;You can perform an assignment to System.Threading.CurrentThread.ApartmentState as one of the first statements of your main method (or of your thread procedure if you do a Thread.Start).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l2 level1 lfo4; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;3)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;You can accept the CLR&amp;#8217;s default of MTA.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So what&amp;#8217;s wrong with each of these techniques?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The first technique is the preferred method, and it works very well for C#.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After some tweaks to the VB.NET compiler before we shipped V1, it worked well for VB too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Managed C++ still doesn&amp;#8217;t properly support this technique.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The reason is that the entrypoint of a managed C++ EXE isn&amp;#8217;t actually your &amp;#8216;main&amp;#8217; routine.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, it&amp;#8217;s a method inside the C-runtime library.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That method eventually delegates to your &amp;#8216;main&amp;#8217; routine.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the CLR doesn&amp;#8217;t scan through the closure of calls from the entrypoint when looking for the custom attribute that defines the threading model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the CLR doesn&amp;#8217;t find it on the method that is the EXE&amp;#8217;s entrypoint, it stops looking.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The net result is that your attribute is quietly ignored for C++.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I&amp;#8217;m told that this will be addressed in Whidbey, by having the linker propagate the attribute from &amp;#8216;main&amp;#8217; to the CRT entrypoint.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And indeed this is how the VB.NET compiler works today.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;What&amp;#8217;s wrong with the second technique?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, it is subject to a race condition.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Before the CLR can actually call your thread procedure, it may first call some module constructors, class constructors, AssemblyLoad notifications and AssemblyResolve notifications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All of this execution occurs on the thread that was just created.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What happens if some of these methods set the thread&amp;#8217;s ApartmentState before you get a chance?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What happens if they call Windows services like the clipboard that also set the apartment state?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A more likely scenario is that one of these other methods will make a PInvoke call that marshals a BSTR, SAFEARRAY or VARIANT.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even these innocuous operations can force a CoInitializeEx on your thread and limit your ability to configure the thread from your thread procedure.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When you are developing your application, none of the above is likely to occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The real nightmare scenario is that a future version of the CLR will provide a JIT that inlines a little more aggressively, so some extra class constructors execute before your thread procedure.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, you will ship an application that is balanced on a knife edge here, and this will become an App Compatibility issue for all of us.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(See &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/11/10/51554.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/cbrumme/archive/2003/11/10/51554.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; for more details on the sort of thing we worry about here).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In fact, for the next release of the CLR we are seriously considering making it impossible to set the apartment state on a running thread in this manner.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At a minimum, you should expect to see a Customer Debug Probe warning of the risk here.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And the third technique from above has a similar problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Recall that threads in the MTA can be explicitly placed there through a CoInitializeEx call, or they can be implicitly treated as being in the MTA because they haven&amp;#8217;t been placed into an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The difference between these two cases is significant.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If a thread is explicitly in the MTA, any attempt to configure it as an STA thread will fail with an error of RPC_E_CHANGED_MODE.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By contrast, if a thread is implicitly in the MTA it can be moved to an STA by calling CoInitializeEx.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is more likely than it may sound.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you attempt a clipboard operation, or you call any number of other Windows services, the code you call may attempt to place your thread in the STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And when you accept the CLR default behavior, it currently leaves the thread implicitly in the MTA and therefore is subject to reassignment.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is another place where we are seriously considering changing the rules in the next version of the CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rather than place threads implicitly in the MTA, we are considering making this assignment explicit and preventing any subsequent reassignment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once again, our motivation is to reduce the App Compat risk for applications after they have been deployed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Speaking of race conditions and apartments, the CLR has a nasty bug which was introduced in V1 and which we have yet to remove.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;ve already mentioned that any threads that aren&amp;#8217;t in STAs or explicitly in the MTA are implicitly in the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s not strictly true.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These threads are only in the MTA if there is an MTA for them to be in.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There is an MTA if OLE is active in the process and if at least one thread is explicitly in the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When this is the case, all the other unconfigured threads are implicitly in the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if that one explicit thread should terminate or CoUninitialize, then OLE will tear down the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A different MTA may be created later, when a thread explicitly places itself into it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And at that point, all the unconfigured threads will implicitly join it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But this destruction and recreation of the MTA has some serious impacts on COM Interop.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, any changes to the apartment state of a thread can confuse our COM Interop layer, cause deadlocks on downlevel platforms, and lead to memory leaks and violation of OLE rules.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Let&amp;#8217;s look at how this specific race condition occurs first, and then I&amp;#8217;ll talk about the larger problems here.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;An unmanaged thread CoInitializes itself for the MTA and calls into managed code.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;While in managed code, that thread introduces some COM objects to our COM Interop layer in the form of RCWs, perhaps by &amp;#8216;new&amp;#8217;ing them from managed code.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The CLR notices that the current thread is in the MTA, and realizes that it must &amp;#8220;keep the MTA alive.&amp;#8221;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We signal the Finalizer thread to put itself explicitly into the MTA via CoInitializeEx.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The unmanaged thread returns out to unmanaged code where it either dies or simply calls CoUninitialize.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The MTA is torn down.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma size=2&gt;The Finalizer thread wakes up and explicitly CoInitializes itself into the MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Oops.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s too late to keep the original MTA alive and it has the effect of creating a new MTA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At least &lt;I&gt;this&lt;/I&gt; one will live until the end of the process.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;As far as I know, this is the only race condition in the CLR that we haven&amp;#8217;t fixed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Why have we ignored it all these years?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, we&amp;#8217;ve never seen it reported from the field.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This isn&amp;#8217;t so surprising when you consider that the application often shares responsibility for keeping the MTA alive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Many applications are aware of this obligation and &amp;#8211; if they use COM &amp;#8211; they always keep an outstanding CoInitialize on one MTA thread so the apartment won&amp;#8217;t be torn down.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Second, I generally resist fixing bugs by adding inter-thread dependencies.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It would be all too easy to create a deadlock by making step 3 wait for the Finalizer thread to CoInitialize itself, rather than just signaling it to do so.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is particularly true since the causality of calls from the Finalizer to other threads is often opaque to us, as I&amp;#8217;ll explain later.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we certainly don&amp;#8217;t want to create a dedicated thread for this purpose.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Dedicated threads have a real impact on Terminal Server scenarios, where the cost of one thread in a process is multiplied by all the processes that are running.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if we were prepared to pay this cost, we would want to create this thread lazily.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But synchronizing with the creation of another thread is always a dangerous proposition.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thread creation involves taking the OS loader lock and making DLL_THREAD_ATTACH notifications to all the DllMain routines that didn&amp;#8217;t explicitly disable these calls.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The bottom line is that the fix is expensive and distasteful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it speaks to a more general problem, where many different components in a process may be individually spinning up threads to keep the MTA from being recycled.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A better solution is for OLE to provide an API to keep this apartment alive, without requiring all those dedicated threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the approach that we are pursuing for the long term.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In our general cleanup of the CLR&amp;#8217;s treatment of CoInitialize, we are also likely to change the semantics of assigning the current thread&amp;#8217;s ApartmentState to Unknown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In V1 &amp;amp; V1.1 of the CLR, any attempt to set the state to Unknown would throw an ArgumentOutOfRangeException, so we&amp;#8217;re confident that we can make this change without breaking applications.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If the CLR has performed an outstanding CoInitializeEx on this thread, we may treat the assignment to Unknown as a request to perform a CoUninitialize to reverse the operation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Currently, the only way you can CoUninitialize a thread is to PInvoke to the OLE32 service.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And such changes to the apartment state are uncoordinated with the CLR.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Now why does it matter if the apartment state of a thread changes, without the CLR knowing?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It matters because:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo6; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The CLR may hold RCWs over COM objects in the apartment that is about to disappear.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Without a notification, we cannot legally release those pUnks. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;As I&amp;#8217;ve already mentioned, we break the rules here and attempt to Release anyway.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it&amp;#8217;s still a very bad situation and sometimes we will end up leaking.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo6; tab-stops: list .5in"&gt;&lt;SPAN style="mso-bidi-font-family: Tahoma; mso-fareast-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The CLR will perform limited pumping of STA threads when you perform managed blocking (e.g. WaitHandle.WaitOne).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we are on a recent OS, we can use the IComThreadingInfo interface to efficiently determine whether we should pump or not.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if we are on a downlevel platform, we would have to call CoInitialize prior to each blocking operation and check for a failure code to absolutely determine the current state of the thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is totally impractical from a performance point of view.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So instead we cache what we believe is the correct apartment state of the thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the application performs a CoInitialize or CoUninitialize without informing us, then our cached knowledge is stale.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So on downlevel platforms we might neglect to pump an STA (which can cause deadlocks).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or we may attempt to pump an MTA (which can cause deadlocks).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Incidentally, if you ever run managed applications under a diagnostic tool like AppVerifier, you may see complaints from that tool at process shutdown that we have leaked one or more CoInitialize calls.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a well-behaved application, each CoInitialize would have a balancing CoUninitialize.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, most processes are not so well-behaved.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s typical for applications to terminate the process without unwinding all the threads of the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There&amp;#8217;s a very detailed description of the CLR&amp;#8217;s shutdown behavior at &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The bottom line here is that the CLR is heavily dependent on knowing exactly when apartments are created and destroyed, or when threads become associated or disassociated with those apartments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the CLR is largely out of the loop when these operations occur, unless they occur through managed APIs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, we are rarely informed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For an extreme example of this, the Shell has APIs which require an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the calling thread is implicitly in the MTA, these Shell APIs CoInitialize that calling thread into an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As the call returns, the API will CoUnitialize and rip down the apartment.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We would like to do better here over time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But there are some pretty deep problems and most solutions end up breaking an important scenario here or there.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Back to Pumping&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Enough of the CoInitialize mess.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I mentioned above that managed blocking will perform some pumping when called on an STA thread.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Managed blocking includes a contentious Monitor.Enter, WaitHandle.WaitOne, WaitHandle.WaitAny, GC.WaitForPendingFinalizers, our ReaderWriterLock and Thread.Join.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It also includes anything else in FX that calls down to these routines.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One noticeable place where this happens is during COM Interop.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are pathways through COM Interop where a cache miss occurs on finding an appropriate pUnk to dispatch a call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At those points, the COM call is forced down a slow path and we use this as an opportunity to pump a little bit.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We do this to allow the Finalizer thread to release any pUnks on the current STA, if the application is neglecting to pump.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Remember those ASP Compat and Console client scenarios?)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a questionable practice on our part.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It causes reentrancy at a place where it normally could never occur in pure unmanaged scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it allows a number of applications to successfully run without clogging up the Finalizer thread. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, managed blocking does not include PInvokes directly to any of the OS blocking services.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And keep in mind that if you PInvoke to the OS blocking services directly, the CLR will no longer be able to take control of your thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Operations like Thread.Interrupt, Thread.Abort and AppDomain.Unload will be indefinitely delayed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Did you notice that I neglected to mention WaitHandle.WaitAll in the list of managed blocking opeprations?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because we don&amp;#8217;t allow you to call WaitAll from an STA thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The reason is rather subtle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When you perform a pumping wait, at some level you need to call MsgWaitForMultipleObjectsEx, or a similar Msg* based variant.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the semantics of a WAIT_ALL on an OS MsgWaitForMultipleObjectsEx call is rather surprising and not what you want at all.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It waits for all the handles to be signaled AND for a message to arrive at the message queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, all your handles could be signaled and the application will keep blocking until you nudge the mouse!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ugh.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We&amp;#8217;ve toyed with some workarounds for this case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, you could imagine spinning up an MTA thread and having it perform the blocking operation on the handles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When all the handles are signaled, it could set another event.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The STA thread would do a WaitHandle.WaitOne on that other event.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This gives us the desired behavior that the STA thread wakes up when all handles are signaled, and it still pumps the message queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, if any of those handles are &amp;#8220;thread-owned&amp;#8221;, like a Mutex, then we have broken the semantics.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Our sacrificial MTA thread now owns the Mutex, rather than the STA thread.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Another technique would be to put the STA thread into a loop.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each iteration would ping the handles with a brief timeout to see if it could acquire them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then it would check the message queue with a PeekMessage or similar technique, and then iterate.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a terrible solution for battery-powered devices or for Terminal Server scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What used to be efficient blocking is now busily spinning in a loop.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if no messages actually arrive, we have disturbed the fairness guarantees of the OS blocking primitives by pinging.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;A final technique would be to acquire the handles one by one, using WaitOne.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is probably the worst approach of all.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The semantics of an OS WAIT_ALL are that you will either get no handles or you will get all of them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is critical to avoiding deadlocks, if different parts of the application block on the same set of handles &amp;#8211; but fill the array of handles in random order.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I keep saying that managed blocking will perform &amp;#8220;some pumping&amp;#8221; when called on an STA thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Wouldn&amp;#8217;t it be great to know exactly what will get pumped?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, pumping is a black art which is beyond mortal comprehension.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On Win2000 and up, we simply delegate to OLE32&amp;#8217;s CoWaitForMultipleHandles service.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And before we wrote the initial cut of our pumping code for NT4 and Win9X, I thought I would glance through CoWaitForMultipleHandles to see how it is done.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is many, many pages of complex code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it uses special flags and APIs that aren&amp;#8217;t even available on Win9X.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The code we finally wrote for the downlevel platforms is relatively simple.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We gather the list of hidden OLE windows associated with the current STA thread and try to restrict our pumping to the COM calls which travel through them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, a lot of the pumping complexity is in USER32 services like PeekMessage.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Did you know that calling PeekMessage for one window will actually cause SendMessages to be dispatched on other windows belonging to the same thread?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is another example of how someone made a tradeoff between reentrancy and deadlocks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case, the tradeoff was made in favor of reentrancy by someone inside USER32.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;By now you may be thinking &amp;#8220;Okay.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Pump more and I get reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Pump less and I get deadlocks.&amp;#8221;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But of course the world is more complicated than that.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, the Finalizer thread may synchronously call into the main GUI STA thread, perhaps to release a pUnk there, as we have seen.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The causality from the Finalizer thread to the main GUI STA thread is invisible to the CLR (though the CLR Security Lead recently suggested using OLE channel hooks as a technique for making this causality visible).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the main GUI STA thread now calls GC.WaitForPendingFinalizers in order to pump, there&amp;#8217;s a possibility of a deadlock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That&amp;#8217;s because the GUI STA thread must wait for the Finalizer thread to drain its queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the Finalizer thread cannot drain its queue until the GUI thread has serviced its incoming synchronous call from the Finalizer.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Reentrancy, Avalon, Longhorn and the Client&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Ah, reentrancy again.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;From time to time, customers inside or outside the company discover that we are pumping messages during managed blocking on an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a legitimate concern, because they know that it&amp;#8217;s very hard to write code that&amp;#8217;s robust in the face of reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, one internal team completely avoids managed blocking, including almost any use of FX, for this reason.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Avalon was very upset, too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I&amp;#8217;m not sure how much detail they have disclosed about their threading model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it&amp;#8217;s certainly not my place to reveal what they are doing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Suffice it to say that their model is an explicit rental model that does not presume thread affinity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you&amp;#8217;ve read this far, I&amp;#8217;m sure you approve of their decision.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Avalon must necessarily coexist with STAs, but Avalon doesn&amp;#8217;t want to require them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR and Avalon have a shared long term goal of driving STAs out of the platform.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But, realistically, this will take decades.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Avalon&amp;#8217;s shorter term goal is to allow some useful GUI applications to be written without STAs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even this is quite difficult.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you call the clipboard today, you will have an STA.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Avalon also has made a conscious design choice to favor deadlocks over reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In my opinion, this is an excellent goal.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Deadlocks are easily debugged.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Reentrancy is almost impossible to debug.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, it results in odd inconsistencies that manifest over time.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In order to achieve their design goals, Avalon requires the ability to control the CLR&amp;#8217;s pumping. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;And since we&amp;#8217;ve had similar requests from other teams inside and outside the company, this is a reasonable feature for us to provide.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;V1 of the CLR had a conscious goal of making as much legacy VB and C++ code work as was possible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we saw the number of applications that failed to pump, we had no choice but to insert pumping for them &amp;#8211; even at the cost of reentrancy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Avalon is in a completely different position.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All Avalon code is new code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They are in a great position to define an explicit model for pumping, and then require that all new applications rigorously conform to that model.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Indeed, as much as I dislike STAs, I have a bigger concern about Longhorn and its client focus.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Historically, Microsoft has built a ton of great functionality and added it to the platform.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But that functionality is often mixed up with various client assumptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;STAs are probably the biggest of those assumptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Shell is an example of this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It started out as a user-focused set of services, like the namespace.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it&amp;#8217;s growing into something that&amp;#8217;s far more generally useful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To the extent that the Shell wants to take its core concepts and make them part of the base managed Longhorn platform, it needs to shed the client focus.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The same is true of Office.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For instance, I want to write some code that navigates to a particular document through some namespace and then processes it in some manner.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I want that exact same code to run correctly on the client and on the server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On the client, my processing of that document should not make the UI unresponsive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On the server, my processing of that document should not cause problems with scalability or throughput.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Historically, this just hasn&amp;#8217;t been the case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have an opportunity to correct this problem once, with the major rearchitecture that is Longhorn.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But although Longhorn will have both client and server releases, I worry that we might still have a dangerous emphasis on the client.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This may be one of the biggest risks we face in Longhorn.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Winding Down&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Finally, I feel a little bad about picking something I don&amp;#8217;t like and writing about it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But there&amp;#8217;s a reason that this topic came up.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Last week, a customer in &lt;st1:country-region w:st="on"&gt;&lt;st1:place w:st="on"&gt;Japan&lt;/st1:place&gt;&lt;/st1:country-region&gt; was struggling with using mshtml.dll to crack some HTML files from inside ASP.NET.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s the obvious thing to do.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Clearly &amp;#8216;mshtml&amp;#8217; stands for Microsoft HTML and clearly this is how we expect customers to process files in this format.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Unfortunately, MSHTML was written as client-side functionality.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, I&amp;#8217;m told that it drives its own initialization by posting Windows messages back to itself and waiting for them to be pumped.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So if you aren&amp;#8217;t pumping an STA, you aren&amp;#8217;t going to get very far.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There&amp;#8217;s that disturbing historical trend at Microsoft to combine generally useful functionality with a client bias again!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We explained to the customer the risks of using client components on a server, and the pumping behavior that is inherent in managed blocking on an STA.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After we had been through all the grisly details, the customer made the natural observation:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;None of this is written down anywhere.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Well, I still never talked about a mysterious new flag to CoWaitForMultipleHandles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or how custom implementations of IMessageFilter can cause problems.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or the difference between &lt;st1:place w:st="on"&gt;Main&lt;/st1:place&gt; and Single. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Or the relationship between apartments and COM+ contexts and ServicedComponents.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or the amazing discovery that OLE32 sometimes requires you to pump the MTA if you have DCOM installed on Win9X.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But I&amp;#8217;m sure that at this point I&amp;#8217;ve said far more than most people care to hear about this subject. &lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=66219" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item><item><title>Access to old blogs</title><link>http://blogs.msdn.com/b/cbrumme/archive/2003/11/10/51572.aspx</link><pubDate>Mon, 10 Nov 2003 20:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:51572</guid><dc:creator>cbrumme</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=51572</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2003/11/10/51572.aspx#comments</comments><description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;
    &lt;p&gt;
        By default, old blogs are truncated from this web site.&amp;#160; If you want to read
        old entries that have scrolled off, go to the CATEGORIES section at the right hand
        side of the web page.&amp;#160; Select CLR (rss) and you'll see the full list.
    &lt;/p&gt;
&lt;/body&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51572" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/Chat/">Chat</category></item><item><title>The PDC and Application Compatibility, but still no Hosting</title><link>http://blogs.msdn.com/b/cbrumme/archive/2003/11/10/51554.aspx</link><pubDate>Mon, 10 Nov 2003 20:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:51554</guid><dc:creator>cbrumme</dc:creator><slash:comments>31</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=51554</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2003/11/10/51554.aspx#comments</comments><description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;The PDC has happened, which means two things.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        can post some of my (slightly self-censored) reactions to the show, and I can talk
        about what we ve disclosed about Whidbey and Longhorn more freely.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        this particular case, I had promised to talk about the deep changes we re making
        in Whidbey to allow you to host the CLR in your process.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As
        you ll see, I got side tracked and ended up discussing Application Compatibility
        instead.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;But first, my impressions of the PDC:&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;The first keynote, with Bill, Jim
        &amp;amp; Longhorn, was guaranteed to be good.&amp;#160; It had all the coolness of Avalon,
        WinFS and Indigo, so of course it was impressive.&amp;#160; In fact, throughout all the
        sessions I attended, I was surprised by the &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;apparent&lt;/i&gt;&lt;/b&gt; polish
        and maturity of Longhorn.&amp;#160; In my opinion, Avalon looked like it is the most mature
        and settled.&amp;#160; Indigo also looked surprisingly real.&amp;#160; WinFS looked good in
        the keynote, where it was all about the justification for the technology.&amp;#160; But
        in the drill-down sessions, I had the sense that it s not as far along as the others.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Hopefully all the attendees realize
        that Longhorn is still a long way off.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        s hard to see from the demos, but a lot of fundamental design issues and huge missing
        pieces remain.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font size="2"&gt;&lt;span style="FONT-FAMILY: Arial"&gt;Incidentally, I still can t believe
        that we picked WinFX to describe the extended managed frameworks and WinFS to describe
        the new storage system.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;One of those
        names has got to go.&lt;/span&gt;&lt;span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'"&gt; 
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'"&gt;&amp;#160;&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;I was worried that the Whidbey keynote
        on Tuesday would appear mundane and old-fashioned by comparison.&amp;#160; But to an audience
        of developers, Eric's keynote looked very good indeed.&amp;#160; Visual Studio looked
        better than I've ever seen it.&amp;#160; The device app was so easy to write that I feel
        I&amp;#160;could build a FedEx-style package tracking application in a weekend.&amp;#160;
        The 
        &lt;st1:City w:st="on"&gt;
            &lt;st1:place w:st="on"&gt;high 
point&lt;/st1:place&gt;
        &lt;/st1:City&gt;
        of this keynote was ASP.NET.&amp;#160; I hadn't been paying attention to what they've
        done recently, so I was blown away by the personalization system and by the user-customizable
        web pages.&amp;#160; If I had seen a site like that, I would have assumed the author spent
        weeks getting it to work properly.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        s hard to believe this can all be done with drag-and-drop.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;In V1, ASP.NET hit a home run by focusing
        like a laser beam on the developer experience.&amp;#160; Everyone put so much effort into
        building apps, questioning why each step was necessary, and refining the process.&amp;#160;
        It's great to see that they continue to follow that same discipline.&amp;#160; In the
        drill-down sessions, over and over again I saw that focus resulting in a near perfect
        experience for developers.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;There are
        some other teams, like Avalon, that seem to have a similar religion and are obtaining
        similar results.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;(Though Avalon desperately
        needs some tools support.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Notepad is
        fine for authoring XAML in demos, but I wouldn t want to build a real application
        this way).&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Compared to ASP.NET, some other teams
        at Microsoft are still living in the Stone Age.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Those
        teams are still on a traditional cycle of building features, waiting for customers
        to build applications with those features, and then incorporating any feedback.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Beta
        is way too late to find out that the programming model is clumsy.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        shouldn t be shirking our design responsibilities like this.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Anyway, the 3rd keynote (from Rick
        Rashid &amp;amp; Microsoft Research) should have pulled it all together.&amp;#160; I think
        the clear message should have been something like:&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt 0.5in"&gt;
        &lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Whidbey
        is coming next and has great developer features.&amp;#160; After that, Longhorn will arrive
        and will change everything.&amp;#160; Fortunately, Microsoft Research is looking 10+ years
        out, so you can be sure we will increasingly drive the whole industry.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;This should have been an easy story
        to tell.&amp;#160; The fact is that MSR is a world class research institution.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Browse
        the Projects, Topics or People categories at &lt;/font&gt;&lt;a href="http://research.microsoft.com/"&gt;&lt;font size="2"&gt;http://research.microsoft.com&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt; and
        you ll see many  name brand researchers like Butler Lampson and Jim Gray.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;You
        will see tremendous breadth on the areas under research, from pure math and algorithms
        to speech, graphics and natural language.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;There
        are even some esoterica like nanotech and quantum computing.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        should have used the number of published papers and other measurements to compare
        MSR with other research groups in the software industry, and with major research universities.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
        then we should have shown some&amp;#160;whiz-bang demos of about 2 minutes each.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Unfortunately, I think instead we
        sent a message that  Interesting technology comes from Microsoft product groups,
        while MSR is largely irrelevant. &lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Yet
        nothing could be further from the truth.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Even
        if I restrict consideration to the CLR, MSR has had a big impact.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Generics
        is one of the biggest feature added to the CLR, C# or the base Frameworks in Whidbey.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        feature was added to the CLR by MSR team members, who now know at least as much about
        our code base as we do.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;All the CLR
        s plans for significantly improved code quality and portable compilers depend on a
        joint venture between MSR and the compiler teams.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;To
        my knowledge, MSR has used the CLR to experiment with fun things like transparent
        distribution, reorganizing objects based on locality, techniques for avoiding security
        stack crawls, interesting approaches to concurrency, and more.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;SPOT
        (Smart Object Personal Technology) is a wonderful example of what MSR has done with
        the CLR s basic IL and metadata design, eventually leading to a very cool product.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;In my opinion, Microsoft Research
        strikes a great balance between long term speculative experimentation and medium term
        product-oriented improvements.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I wish
        this had come across better at the PDC.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b&gt;&lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Trends&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;In the 6+ years I ve been at Microsoft,
        we ve had 4 PDCs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This is the first
        one I ve actually attended, because I usually have overdue work items or too many
        bugs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;(I ve missed all 6 of our mandatory
        company meetings for the same reason).&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;So
        I really don t have a basis for comparison.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;I guess I had expected to be beaten
        up about all the security issues of the last year, like Slammer and Blaster.&amp;#160;
        And I had expected developers to be interested in all aspects of security.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Instead,
        the only times the topic came up in my discussions is when I raised it.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;However, some of my co-workers did
        see a distinct change in the level of interest in security.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
        example, Sebastian Lange and Ivan Medvedev gave a talk on managed security to an audience
        of 700-800.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They reported a real upswing
        in awareness and knowledge on the part of all PDC attendees.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;But consider a talk I attended on
        Application Compatibility.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;At a time
        when most talks were overflowing into the hallways, this talk filled less than 50
        seats of a 500 to 1000 seat meeting room.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        know that AppCompat is critically important to IT.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
        it s a source of friction for the entire industry, since everyone is reluctant to
        upgrade for fear of breaking something.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        for most developers this is all so boring compared to the cool visual effects we can
        achieve with a few lines of XAML.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Despite a trend to increased interest
        in security on the part of developers, I suspect that security remains more of an
        IT operations concern than it does a developer concern.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
        although the events of the last year or two have got more developers excited about
        security (including me!), I doubt that we will ever get developers excited about more
        mundane topics like versioning, admin or compatibility.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        latter stuff is dead boring.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;That doesn t mean that the industry
        is doomed.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Instead, it means that modern
        applications must obtain strong versioning, compatibility and security guarantees
        by default  rather than through deep developer involvement.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Fortunately,
        this is entirely in keeping with our long term goals for managed code.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;With the first release of the CLR,
        the guarantees for managed applications were quite limited.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        guaranteed memory safety through an accurate garbage collector, type safety through
        verification, binding safety through strong names, and security through CAS.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;(However,
        I think we would all agree that our current support for CAS still involves far too
        much developer effort and not enough automated guarantees.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Our
        security team has some great long-term ideas for addressing this.)&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;More importantly, we expressed programs
        through metadata and IL, so that we could expand the benefits of reasoning about these
        programs over time.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And we provided metadata
        extensibility in the form of Custom Attributes and Custom Signature Modifiers, so
        that others could add to the capabilities of the managed environment without depending
        on the CLR team s schedule.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;FxCop (&lt;/font&gt;&lt;a href="http://www.gotdotnet.com/team/fxcop/"&gt;&lt;font size="2"&gt;http://www.gotdotnet.com/team/fxcop/&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt;)
        is an obvious example of how we can benefit from this ability to reason about programs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;All
        teams developing managed code at Microsoft are religious about incorporating this
        tool into their build process.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And since
        FxCop supports adding custom rules, we have added a large number of Microsoft-specific
        or product-specific checks.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b&gt;&lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Churn and Application Breakage&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;We also have some internal tools that
        allow us to compare different versions of assemblies so we can discover inadvertent
        breaking changes.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Frankly, these tools
        are still maturing.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Even in the 
        &lt;st1:place w:st="on"&gt;
            &lt;st1:City w:st="on"&gt;Everett&lt;/st1:City&gt;
        &lt;/st1:place&gt;
        timeframe, they did a good job of blatant violations like the removal of a public
        method from a class or addition of a method to an interface.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        they didn t catch changes in serialization format, or changes to representation after
        marshaling through PInvoke or COM Interop.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As
        a result, we shipped some unintentional breaking changes in 
        &lt;st1:City w:st="on"&gt;
            &lt;st1:place w:st="on"&gt;Everett&lt;/st1:place&gt;
        &lt;/st1:City&gt;
        , and until recently we were on a path to do so again in Whidbey.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;As far as I know, these tools still
        don t track changes to CAS constructs, internal dependency graphs, thread-safety
        expectations, exception flow (including a static replacement for the  checked exceptions
        feature), reliability contracts, or other aspects of execution.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Some
        of these checks will probably be added over time, perhaps by adding additional metadata
        to assemblies to reveal the developer s intentions and to make automated validation
        more tractable.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Other checks seem like
        research projects or are more appropriate for dynamic tools rather than static tools.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        s very encouraging to see teams inside and outside of Microsoft working on this.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;I expect that all developers will
        eventually have access to these or similar tools from Microsoft or 3&lt;sup&gt;rd&lt;/sup&gt; parties,
        which can be incorporated into our build processes the way FxCop has been.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;Sometimes applications break when
        their dependencies are upgraded to new versions.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        classic example of this is Win95 applications which broke when the operating system
        was upgraded to WinXP.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Sometimes this
        is because the new versions have made breaking changes to APIs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        sometimes it s because things are just  different .&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        classic case here is where a test case runs perfectly on a developer s machine, but
        fails intermittently in the test lab or out in the field.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        difference in environment might be obvious, like a single processor box vs. an 8-way.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Yet
        all too often it s something truly subtle, like a DLL relocating when it misses its
        preferred address, or the order of DllMain notifications on a DLL_THREAD_ATTACH.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        those cases, the change in environment is not the culprit.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Instead,
        the environmental change has finally revealed an underlying bug or fragility in the
        application that may have been lying dormant for years.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;&lt;font size="2"&gt;The managed environment eliminates
        a number of common fragilities, like the double-free of memory blocks or the use of
        a file handle or Event that has already been closed.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        it certainly doesn t guarantee that a multi-threaded program which appears to run
        correctly on a single processor will also execute without race conditions on a 32-way
        NUMA box.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The author of the program must
        use techniques like code reviews, proof tools and stress testing to ensure that his
        code is thread-safe.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-FAMILY: Arial"&gt;
        &lt;o:p&gt;
            &lt;font size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;The situation that worries me the most is when an application
        relies on accidents of current FX and CLR implementations.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;These
        dependencies can be exceedingly subtle.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Here are some examples of breakage that we have encountered,
        listed in the random order they occur to me:&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="1"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Between V1.1 and Whidbey, the implementation of reflection
            has undergone a major overhaul to improve access times and memory footprint.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;One
            consequence is that the order of members returned from APIs like Type.GetMethods has
            changed.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The old order was never documented
            or guaranteed, but we ve found programs  including our own tests  which assumed
            stability here.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt 0.25in"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="2"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Structs and classes can specify Sequential, Explicit
            or AutoLayout.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In the case of AutoLayout,
            the CLR is free to place members in any order it chooses.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Except
            for alignment packing and the way we chunk our GC references, our layout here is currently
            quite predictable.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But in the future
            we hope to use access patterns to guide our layout for increased locality.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Any
            applications that predict the layout of AutoLayout structs and classes via unsafe
            coding techniques are at risk if we pursue that optimization.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="3"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Today, finalization occurs on a single Finalizer thread.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
            scalability and robustness reasons, this is likely to change at some point.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Also,
            the GC already perturbs the order of finalization.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
            instance, a collection can cause a generation boundary to intervene between two instances
            that are normally allocated consecutively.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Within
            a given process run, there will likely be some variation in finalization sequence.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
            for two objects that are allocated consecutively by a single thread, there is a high
            likelihood of predictable ordering.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
            we all know how easy it is to make assumptions about this sort of thing in our code.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 3pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="4"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;In an earlier blog (&lt;/font&gt;&lt;a href="http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/e55664b4-6471-48b9-b360-f0fa27ab6cc0"&gt;&lt;font face="Tahoma" size="2"&gt;http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/e55664b4-6471-48b9-b360-f0fa27ab6cc0&lt;/font&gt;&lt;/a&gt;&lt;font face="Tahoma" size="2"&gt;),
            I talked about some of the circumstances that impact when the JIT will stop reporting
            a reference to the GC.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;These include
            inlining decisions, register allocation, and obvious differences like X86 vs. AMD64
            vs. IA64.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Clearly we want the freedom
            to chase better code quality with JIT compilers and NGEN compilers in ways that will
            substantially change these factors.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Just
            yesterday an internal team reported a GC bug  on multi-processor machines only 
            that we quickly traced to confusion over lifetime rules and bad practice in the application.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;One
            finalizable object was accessing some state in another finalizable object, in the
            expectation that the first object was  live because it was the  this argument
            of an active method call. &lt;/font&gt;
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="5"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;During V1.1 Beta testing, a customer complained about
            an application we had broken.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This application
            contained unmanaged code that reached back into its caller s stack to retrieve a
            GCHandle value at an offset that had been empirically discovered.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
            unmanaged code then transitioned into managed and redeemed the supposed handle value
            for the object it referenced.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This usually
            worked, though it was clearly dependent on filthy implementation details.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Unfortunately,
            the System.EnterpriseServices pathways leading to the unmanaged application were somewhat
            variable.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Under certain circumstances,
            the stack was not what the unmanaged code predicted.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
            V1, the value at the predicted spot was always a 0 and the redemption attempt failed
            cleanly.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In V1.1, the value at that stack
            location was an unrelated garbage value.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
            consequence was a crash inside mscorwks.dll and  Fail Fast termination of the process.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="6"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;In V1 and V1.1, Object.GetHashCode() can be used to obtain
            a hashcode for any object.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;However, our
            implementation happened to return values which tended to be small ascending integers.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Furthermore,
            these values happened to be unique across all reachable instances that were hashed
            in this manner.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In other words, these
            values were really object identifiers or OIDs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Unfortunately,
            this implementation was a scalability killer for server applications running on multi-processor
            boxes.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;So in Whidbey Object.GetHashCode()
            is now all we ever promised it would be: an integer with reasonable distribution but
            no uniqueness guarantees.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It s a great
            value for use in HashTables, but it s sure to disappoint some existing managed applications
            that relied on uniqueness.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="7"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;In V1 and V1.1, all string literals are Interned as described
            in &lt;/font&gt;&lt;a href="http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/7943b9be-cca9-41e1-8a83-3d7a0dbba270"&gt;&lt;font face="Tahoma" size="2"&gt;http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/7943b9be-cca9-41e1-8a83-3d7a0dbba270&lt;/font&gt;&lt;/a&gt;&lt;font face="Tahoma" size="2"&gt;.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
            noted there that it is a mistake to depend on Interning across assemblies.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That
            s because the other assembly might start to compose a String value which it originally
            specified as a literal.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In Whidbey, assemblies
            can opt-in or opt-out of our Interning behavior.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
            new freedom is motivated by a desire to support faster loading of assemblies (particularly
            assemblies that have been NGEN ed).&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
            ve seen some tests fail as a result.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="8"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;I ve seen some external developers use a very fragile
            technique based on their examination of Rotor sources.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They
            navigate through one of System.Threading.Thread s private fields (DONT_USE_InternalThread)
            to an internal unmanaged CLR data structure that represents a running managed thread.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;From
            there, they can pluck interesting information like the Thread::ThreadState bit field.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;None
            of these data structures are part of our contract with managed applications and all
            of them are sure to change in future releases.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
            only reason the ThreadState field is at a stable offset in our internal Thread struct
            today is that its frequency of access merits putting it near the top of the struct
            for good cache-line filling behavior.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="9"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Reflection allows highly privileged code to access private
            members of arbitrary types.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I am aware
            of dozens of teams inside and outside of Microsoft which rely on this mechanism for
            shipping products.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Some of these uses
            are entirely justified, like the way Serialization accesses private state that the
            type author marked as [Serializable()].&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Many
            other uses rather questionable, and a few are truly heinous.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Taken
            to the extreme, this technique converts every internal implementation detail into
            a publicly exposed API, with the obvious consequences for evolution and application
            compatibility.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="10"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Assembly loading and type resolution can happen on very
            different schedules, depending on how your application is running.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
            ve seen applications that misbehave based on NGEN vs. JIT, domain-neutral vs. per-domain
            loading, and the degree to which the JIT inlines methods.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
            example, one application created an AppDomain and started running code in it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That
            code subsequently modified the private application directory and then attempted to
            load an assembly from that directory.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Of
            course, because of inlining the JIT had already attempted to load the assembly with
            the original application directory and had failed.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
            correct solution here is to disallow any changes to an AppDomain s application directory
            after code starts executing inside that AppDomain.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
            directory should only be modifiable during the initialization of the AppDomain.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="11"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;In prior blogs, I ve talked about unhandled exceptions
            and the CLR s default policy for dealing with them.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That
            policy is quite involved and hard to defend.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;One
            aspect of it is that exceptions that escape the Finalizer thread or any ThreadPool
            threads are swallowed.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This keeps the
            process running, but it often leaves the application in an inconsistent state.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
            example, locks may not have been released by the thread that took the exception, leading
            to subsequent hangs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Now that the technology
            for reporting process crashes via Watson dumps is maturing, we really want to change
            our default policy for unhandled exceptions so that we Fail Fast with a process crash
            and a Watson upload.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;However, any change
            to this policy will undoubtedly cause many existing applications to stop working.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ol style="MARGIN-TOP: 0in" type="1" start="12"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Despite the flexibility of CAS, most applications still
            run with Full Trust.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I truly believe
            that this will change over time.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
            example, in Whidbey we will have ClickOnce permission elevation and in Longhorn we
            will deliver the Secure Execution Environment or SEE.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Both
            of these features were discussed at the PDC.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;When
            we have substantial code executing in partial trust, we re going to see some unfortunate
            surprises.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For example, consider message
            pumping.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If a Single Threaded Apartment
            thread has some partial trust code on its stack when it blocks (e.g. Monitor.Enter
            on a contentious monitor), then we will pump messages on that thread while it is blocked.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
            the dispatching of a message requires a stack walk to satisfy a security Full Demand,
            then the partially trusted code further back on the stack may trigger a security exception.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Another
            example is related to class constructors.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As
            you probably know, .cctor methods execute on the first thread that needs access to
            a class in a particular AppDomain.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
            the .cctor must satisfy a security demand, the success of the .cctor now depends on
            the accident of what other code is active on the thread s stack.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Along
            the same lines, the .cctor method may fail if there is insufficient stack space left
            on the thread that happens to execute it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;These
            are all well understood problems and we have plans for fixing them.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
            the fixes will necessarily change observable behavior for a class of applications.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;I could fill a lot more pages with this sort of list.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
        our platform is still in its infancy.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Anyway,
        one clear message from all this is that things will change and then applications will
        break.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;But can we categorize these failures and make some sense
        of it all?&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For each failure, we need
        to decide whether the platform or the application is at fault for each case.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
        then we need to identify some rules or mechanisms that can avoid these failures or
        mitigate them.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I see four categories.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Category
        1:&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The application explicitly screws
        itself&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;The easiest category to dispense with is the one where
        a developer intentionally and explicitly takes advantage of a behavior that s/he knows
        is guaranteed to change.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;A perfect example
        of this is #8 above.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Anyone who navigates
        through private members to unmanaged internal data structures is setting himself up
        for problems in future versions.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        responsibility (or irresponsibility in this case) lies with the application.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        my opinion, the platform should have no obligations.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;But consider #5 above.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        s clearly in this same category, and yet opinions on our larger team were quite divided
        on whether we needed to  fix the problem. &lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        spoke to a number of people who definitely understood the incredible difficulty of
        keeping this application running on new versions of the CLR and EnterpriseServices.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        they consistently argued that the operating system has traditionally held itself to
        this sort of compatibility bar, that this is one of the reasons for Windows ubiquity,
        and that the managed platform must similarly step up.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Also, we have to be realistic here.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
        a customer issue like this involves one of our largest accounts, or has been escalated
        through a very senior executive (a surprising number seem to reach Steve Ballmer),
        then we re going to pull out all the stops on a fix or a temporary workaround.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In many cases, our side-by-side support is an adequate
        and simple solution.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Customers can continue
        to run problematic applications on their old bits, even though a new version of these
        bits has also been installed.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For instance,
        the config file for an application can specify an old version of the CLR.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Or
        binding redirects could roll back a specific assembly.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        this technique falls apart if the application is actually an add-in that is dynamically
        loaded into a process like Internet Explorer or SQL Server.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        s unrealistic to lock back the entire managed stack inside Internet Explorer (possibly
        preventing newer applications that use generics or other Whidbey features from running
        there), just so older questionable applications can keep running.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;It s possible that we could provide lock back at finer-grained
        scopes than the process scope in future versions of the CLR.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Indeed,
        this is one of the areas being explored by our versioning team.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Anyway, if we were under sufficient pressure I could
        imagine us building a one-time QFE (patch) for an important customer in this category,
        to help them transition to a newer version  and more maintainable programming techniques.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        if you aren t a Fortune 100 company or Steve Ballmer s brother-in-law, I personally
        hope we would be allowed to ignore any of your applications that are in this category.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Category
        2:&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The platform explicitly screws the
        application&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;I would put #6, #7 and #11 above in a separate category.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Here,
        the platform team wants to make an intentional breaking change for some valid reason
        like performance or reliability.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In fact,
        #10 above is a very special case of this category.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        #10, we would like to break compatibility in Whidbey so that we can provide a stronger
        model that can avoid subsequent compatibility breakage.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        s a paradoxical notion that we should break compatibility now so we can increase future
        compatibility, but the approach really is sensible.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Anyway, if the platform makes a conscious decision to
        break compatibility to achieve some greater goal, then the platform is responsible
        for mitigation.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;At a minimum, we should
        provide a way for broken applications to obtain the old behavior, at least for some
        transition period.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We have a few choices
        in how to do this, and we re likely to pick one based on engineering feasibility,
        the impact of a breakage, the likelihood of a breakage, and schedule pressure:&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ul style="MARGIN-TOP: 0in" type="disc"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;Rely on side-by-side and explicit administrator intervention.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
            other words, the admin notices the application no longer works after a platform upgrade,
            so s/he authors a config file to lock the application back to the old platform bits.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
            approach is problematic because it requires a human being to diagnose a problem and
            intervene.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Also, it has the problems
            I already mentioned with using side-by-side on processes like Internet Explorer or
            SQL Server.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt 0.25in"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ul style="MARGIN-TOP: 0in" type="disc"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;For some changes, it shouldn t be necessary to lock
            back the entire platform stack.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Indeed,
            for many changes the platform could simultaneously support the old and new behaviors.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
            we change our default policy for dealing with unhandled exceptions, we should definitely
            retain the old policy&amp;amp; at least for one release cycle.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ul style="MARGIN-TOP: 0in" type="disc"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;If we expect a significant percentage of applications
            to break when we make a change, we should consider an opt-in policy for that change.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
            eliminates the breakage and the human involvement in a fix.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
            the case of String Interning, we require each assembly to opt-in to the new non-intern
            ed behavior.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;ul style="MARGIN-TOP: 0in" type="disc"&gt;
        &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in"&gt;
            &lt;font face="Tahoma" size="2"&gt;In some cases, we ve toyed with the idea of having the
            opt-in be implicit with a recompile.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
            logic here is that when an application is recompiled against new platform bits, it
            is presumably also tested against those new bits.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
            developer, rather than the admin, will deal with any compatibility issues that arise.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
            re well set up for this, since managed assemblies contain metadata giving us the version
            numbers of the CLR and the dependent assemblies they were compiled against.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Unfortunately,
            execution models like ASP.NET work against us here.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As
            you know, ASP.NET pages are recompiled automatically by the system based on dependency
            changes.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;There is no developer available
            when this happens.&lt;/font&gt; 
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Windows
        Shimming&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Before we look at the next two categories of AppCompat
        failure, it s worth taking a very quick look at one of the techniques that the operating
        system has traditionally used to deal with these issues.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Windows
        has an AppCompat team which has built something called a shimming engine.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Consider what happened when the company tried to move
        consumers from Win95/Win98/WinMe over to WinXP.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They
        discovered a large number of programs which used the GetVersion or the preferred GetVersionEx
        APIs in such a way that the programs refused to run on NT-based systems.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In fact, WinXP did such a good job of achieving compatibility
        with Win9X systems that in many cases the &lt;i style="mso-bidi-font-style: normal"&gt;only&lt;/i&gt; reason
        the application wouldn t run was the version check that the program made at start
        up.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The fix was to change GetVersion
        or GetVersionEx to lie about the version number of the current operating system.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Of
        course, this lie should only be told to programs that need the lie in order to work
        properly.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;I ve heard that this shim which lies about the operating
        system version is the most commonly applied shim we have.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As
        I understand it, at process launch the shimming engine tries to match the current
        process against any entries in its database.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        match could be based on the name, timestamp or size of the EXE, or of other files
        found relative to that EXE like a BMP for the splash screen in a subdirectory.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        entry in the database lists any shims that should be applied to the process, like
        the one that lies about the version.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        shimming engine typically bashes the IAT (import address table) of a DLL or EXE in
        the process, so that its imports are bound to the shim rather than to the normal export
        (e.g. Kernel32!GetVersionEx).&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In addition,
        the shimming engine has other tricks it perform less frequently, like wrapping COM
        objects up with intercepting proxies.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;It s easy to see how this infrastructure can allow applications
        for Win95 to execute on WinXP.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;However,
        this approach has some drawbacks.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;First,
        it s rather labor-intensive.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Someone
        has to debug the application, determine which shims will fix it, and then craft some
        suitable matching criteria that will identify this application in the shimming database.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
        an appropriate shim doesn t already exist, it must be built.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In the best case, the application has some commercial
        significance and Microsoft has done all the testing and shimming.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        if the application is a line of business application that was created in a particular
        company s IT department, Microsoft will never get its hands on it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        ve heard we re now allowing sophisticated IT departments to set up their own shimming
        databases for their own applications  but this only allows them to apply existing
        shims to their applications.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;And  from my skewed point of view  the worst part of
        all this is that it really won t work for managed applications.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For
        managed apps, binding is achieved through strong names, Fusion and the CLR loader.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Binding
        is practically never achieved through DLL imports.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;So it s instructive to look at some of the techniques
        the operating system has traditionally used.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        those techniques don t necessarily apply directly to our new problems.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Anyway, back to our categories&amp;amp; &lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Category
        3:&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The application accidentally screws
        itself&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Category
        4:&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The platform accidentally screws the
        application&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Frankly, I m having trouble distinguishing these two
        cases.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They are clearly distinct categories,
        but it s a judgment call where to draw the line.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        common theme here is that the platform has accidentally exposed some consistent behavior
        which is not actually a guaranteed contract.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        application implicitly acquires a dependency on this consistent behavior, and is broken
        when the consistency is later lost.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In the nirvana of some future fully managed execution
        environment, the platform and tools would never expose consistent behavior unless
        it was part of a guarantee.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Let s look
        at some examples and see how practical this is.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In example #1 above, reflection used to deliver members
        in a stable order.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In Whidbey, that order
        changes.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In hindsight, there s a simple
        solution here.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;V1 of the product could
        have contained a testing mode that randomized the returned order.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        would have exposed the developer to our actual guarantees, rather than to a stronger
        accidental consistency.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Within the CLR,
        we ve used this sort of technique to force us down code paths that otherwise wouldn
        t be exercised.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For example, developers
        on the CLR team all use NT-based (Unicode) systems and avoid Win9X (Ansi) systems.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;So
        our Win9X Ansi/Unicode wrappers wouldn t typically get tested by developers.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;To
        address this, our checked/debug CLR build originally considered the day of the week
        and used Ansi code paths every other day.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        imagine chasing a bug at 
        &lt;st1:time w:st="on" Minute="55" Hour="23"&gt;11:55 PM&lt;/st1:time&gt;
        .&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;When the bug magically disappears on
        your next run at 
        &lt;st1:time w:st="on" Minute="03" Hour="1"&gt;1:03 AM&lt;/st1:time&gt;
        the next morning, you are far too frazzled to think clearly about the reason.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Today,
        we tend to use low order bits in the size of an image like mscorwks.dll or the assembly
        being tested, so our  randomization is now more friendly to testing.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In example #2 above, you could imagine a similar perturbation
        on our AutoLayout algorithms when executing a debug version of an application, or
        when launched from inside a tool like Visual Studio.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;For example #4, the CLR already has internal stress modes
        that force different and aggressive GC schedules.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;These
        can guarantee compaction to increase the likelihood of detecting stale references.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They
        can perform extensive checks of the integrity of the heap, to ensure that the write
        barrier and other mechanisms are effective.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And
        they can ensure that every instruction of JITted managed code that &lt;i style="mso-bidi-font-style: normal"&gt;can&lt;/i&gt; synchronize
        with the GC &lt;i style="mso-bidi-font-style: normal"&gt;will&lt;/i&gt; synchronize with the GC.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        suspect that these modes would do a partial job of eradicating assumptions about lifetimes
        reported by the JIT.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;However, we will
        remain exposed to significantly different code generators (like Rotor s FJIT) or
        execution on significantly different architectures (like CPUs with dramatically more
        registers).&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In contrast with the above difficulty, it s easy to
        imagine adding a new GC stress mode that perturbs the finalization queues, to uncover
        any hidden assumptions about finalization order.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        would address example #3.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Customer Debug Probes, AppVerifier and other
        tools&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;It turns out that the CLR already has a partial mechanism
        for enabling perturbation during testing and removing it on deployed applications.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        mechanism is the Customer Debug Probes feature that we shipped in V1.1.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Adam
        Nathan s excellent blog site has a series of articles on CDPs, which are collected
        together at &lt;/font&gt;&lt;a href="http://blogs.gotdotnet.com/anathan/CategoryView.aspx/Debugging"&gt;&lt;font face="Tahoma" size="2"&gt;http://blogs.gotdotnet.com/anathan/CategoryView.aspx/Debugging&lt;/font&gt;&lt;/a&gt;&lt;font face="Tahoma" size="2"&gt;.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        original goal of CDPs was to counteract the  black box nature of debugging certain
        failures of managed applications, like corruptions of the GC heap or crashes due to
        incorrect marshaling directives.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;These
        probes can automatically diagnose common application errors, like failing to keep
        a marshaled delegate rooted so it won t be collected.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        approach is so much easier than wading through dynamically generated code without
        symbols, because we tell you exactly where your bugs are.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        we re now realizing that we can also use CDPs to increase the future compatibility
        of managed applications if we can perturb current behavior that is likely to change
        in the future.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="mso-spacerun: yes"&gt;&lt;font face="Tahoma" size="2"&gt;&lt;/font&gt;&lt;/span&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Unfortunately, example #6 from above reveals a major
        drawback with the technique of perturbation.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;When
        we built the original implementation of Object.GetHashCode, we simply never considered
        the difference between what we wanted to guarantee (hashing) and what we actually
        delivered (OIDs).&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In hindsight, it is
        obvious.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But I m not convinced that
        we aren t falling into similar traps in our new features.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        might be a little smarter than we were five years ago, but only a little.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Example #10 worries me for similar reasons.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        just don t think we were smart enough to predict that changing the binding configuration
        of an AppDomain  after starting to execute code in that AppDomain  would be so fragile.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;When
        a developer delivers a feature, s/he needs to consider security, thread-safety, programming
        model, key invariants of the code base like GC reporting, correctness, and so many
        other aspects.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It would be amazing if
        a developer consistently nailed each of these aspects for every new feature.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        re kidding ourselves if we think that evolution and unintentional implicit contracts
        will get adequate developer attention on every new feature.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Even if we had perfect foresight and sufficient resources
        to add perturbation for all operations, we would still have a major problem.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        can t necessarily rely on 3&lt;sup&gt;rd&lt;/sup&gt; party developers to test their applications
        with perturbation enabled.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Consider the
        unmanaged AppVerifier experience.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;The operating system has traditionally offered a dynamic
        testing tool called AppVerifier which can diagnose many common unmanaged application
        bugs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;For example, thanks to uploads
        of Watson process dumps from the field, most unmanaged application crashes can now
        be attributed to incorrect usage of dynamically allocated memory.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Yet
        AppVerifier can use techniques like placing each allocation in its own page or leaving
        pages unmapped after release, to deterministically catch overruns, double frees, and
        reads or writes of freed memory.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In other words, there is hard evidence that if every
        unmanaged application had just used the memory checking support of AppVerifier, then
        two out of every three application crashes would be eliminated.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Clearly
        this didn t happen.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Of course, AppVerifier can diagnose far more than just
        memory problems.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And it s very easy
        and convenient to use.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Since testing with AppVerifier is part of the Windows
        Logo compliance program, you would expect that it s used fairly rigorously by ISVs.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And,
        given its utility, you would expect that most IT organizations would use this tool
        for their internal applications.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Unfortunately,
        this isn t the case.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Many applications
        submitted for the Windows Logo actually fail to launch under AppVerifier.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        other words, they violate at least one of the rules before they finish initializing.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;The Windows AppCompat team recognizes that proactive
        tools like AppVerifier are so much better than reactive mitigation like shimming broken
        applications out in the field.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That
        s why they made the AppVerifier tool a major focus of their poorly attended Application
        Compatibility talk that I sat in on at the PDC.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;(Aha!&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        really was going somewhere with all this.)&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;There s got to be a reason why developers don t use
        such a valuable tool.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In my opinion,
        the reason is that AppVerifier is not integrated into Visual Studio.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
        the Debug Properties in VS allowed you to enable AppVerifier and CDP checks, we would
        have much better uptake.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;And if an integrated
        project system and test system could monitor code coverage numbers, and suggest particular
        test runs with particular probes enabled, we would be approaching nirvana.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;b&gt;&lt;font size="2"&gt;&lt;font face="Tahoma"&gt;Winding Down&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Looking at development within Microsoft, one trend is
        very clear:&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Automated tools and processes
        are a wonderful supplement for human developers.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Whether
        we re talking about security, reliability, performance, application compatibility
        or any other measure of software quality, we re now seeing that static and dynamic
        analysis tools can give us guarantees that we will never obtain from human beings.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Bill
        Gates touched on this during his PDC keynote, when he described our new tools for
        statically verifying device driver correctness, for some definition of correctness.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;This trend was very clear to me during the weeks I spent
        on the DCOM / RPCSS security fire drill.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        spent days looking at some clever marshaling code, eventually satisfying myself that
        it worked perfectly.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Then someone else
        wrote an automated attacker and discovered real flaws in just a few hours.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Other
        architects and senior developers scrutinized different sections of the code.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Then
        some researchers from MSR who are focused on automatic program validation ran their
        latest tools over the same code and gave us step-by-step execution models that led
        up to crashes.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Towards the end of the
        fire drill, a virtuous cycle was established.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        code reviewers noticed new categories of vulnerabilities.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Then
        the researchers tried to evolve their tools to detect those vulnerabilities.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Aspects
        of this process were very raw, so the tools sometimes produced a great deal of noise
        in the form of false positives.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But it
        s clear that we were getting real value from Day One and the future potential here
        is enormous.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;One question that always comes up, when we talk about
        adding significant value to Visual Studio through additional tools, is whether Microsoft
        should give away these tools.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It s a
        contentious issue, and I find myself going backwards and forwards on it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;One
        school of thought says that we should give away tools to promote the platform and
        improve all the programs in the Windows ecology.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        the case of tools that make our customers applications more secure or more resilient
        to future changes in the platform, this is a compelling argument.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Another
        school of thought says that Visual Studio is a profit center like any other part of
        the company, and it needs the freedom to charge what the market will bear.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Given that my job is building a platform, you might expect
        me to favor giving away Visual Studio.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        I actually think the profit motive is a powerful mechanism for making our tools competitive.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
        Visual Studio doesn t have P&amp;amp;L responsibility, their offering will deteriorate
        over time.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The best way to know whether
        they ve done all they can to make the best tools possible, is to measure how much
        their customers are willing to pay.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        want Borland to compete with Microsoft on building the best tools at the best price,
        and I want to be able to measure the results of that competition through revenue and
        market penetration.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;In all this, I have avoided really talking about the
        issues of versioning.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Of course, versioning
        and application compatibility are enormously intertwined.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Applications
        break for many reasons, but the typical reason is that one component is now binding
        to a new version of another component.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We
        have a whole team of architects, gathered from around the company, who have been meeting
        regularly for about a year to grapple with the problems of a complete managed versioning
        story.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Unlike managed AppCompat, the
        intellectual investment in managed versioning has been enormous.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Anyway, Application Compatibility remains a relatively
        contentious subject over here.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;There
        s no question that it s a hugely important topic which will have a big impact on
        the longevity of our platform.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But we
        are still trying to develop techniques for achieving compatibility that will be more
        successful than what Windows has done in the past, without limiting our ability to
        innovate on what is still a very young execution engine and set of frameworks.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        have deliberately avoided talking about what some of those techniques might be, in
        part because our story remains incomplete.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;Also, we won t realize how badly AppCompat will bite
        us until we can see a lot of deployed applications that are breaking as we upgrade
        the platform.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;At that point, it s easier
        to justify throwing more resources at the problem.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        by then the genie is out of the bottle&amp;amp; the deployed applications will already
        depend on brittle accidents of implementation, so recovery will be painfully breaking.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In
        a world where we are always under intense resource and schedule pressure, the needs
        of AppCompat must be balanced against performance, security, developer productivity,
        reliability, innovation and all the other  must haves .&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;You know, I really do want to talk about Hosting.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It
        is a truly fascinating subject.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I m
        much more comfortable talking about non-preemptive fiber scheduling than I am talking
        about uninteresting topics like implicit contracts and compatibility trends.&lt;/font&gt; 
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;o:p&gt;
            &lt;font face="Tahoma" size="2"&gt;&amp;#160;&lt;/font&gt; 
        &lt;/o:p&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Tahoma" size="2"&gt;But Hosting is going to have to wait at least a few more
        weeks.&lt;/font&gt; 
    &lt;/p&gt;
&lt;/body&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51554" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item><item><title>The Exception Model</title><link>http://blogs.msdn.com/b/cbrumme/archive/2003/10/01/51524.aspx</link><pubDate>Wed, 01 Oct 2003 20:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:51524</guid><dc:creator>cbrumme</dc:creator><slash:comments>92</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=51524</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2003/10/01/51524.aspx#comments</comments><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I had 
hoped this article would be on changes to the next version of the CLR which 
allow it to be hosted inside SQL Server and other “challenging” 
environments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is more 
generally interesting than you might think, because it creates an opportunity 
for other processes (i.e. &lt;I style="mso-bidi-font-style: normal"&gt;your&lt;/I&gt; 
processes) to host the CLR with a similar level of integration and control.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This includes control over memory usage, 
synchronization, threading (including fibers), extended security models, 
assembly storage, and more.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = 
"urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;However, 
that topic is necessarily related to our next release, and I cannot talk about 
deep details of that next release until those details have been publicly 
disclosed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In late October, 
Microsoft is holding its PDC and I expect us to disclose many details at that 
time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, I’m signed up to be 
a member of a PDC panel on this topic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;If you work on a database or an application server or a similarly 
complicated product that might benefit from hosting the CLR, you may want to 
attend.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;After 
we’ve disclosed the hosting changes for our next release, you can expect a blog 
on hosting in late October or some time in November.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Instead, 
this blog is on the managed exception model.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is an unusual topic for me.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the past, I’ve picked topics where I 
can dump information without having to check any of my facts or do any 
research.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But in the case of 
exceptions I keep finding questions I cannot answer.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At the top level, the managed exception 
model is nice and simple.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But – as 
with everything else in software – the closer you look, the more you 
discover.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So for 
the first time I decided to have some CLR experts read my blog entry before I 
post it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In addition to pointing 
out a bunch of my errors, all the reviewers were unanimous on one point: I 
should write shorter blogs.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, we can’t talk about managed exceptions without first considering Windows 
Structured Exception Handling (SEH).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And we also need to look at the C++ exception model.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because both managed exceptions 
and C++ exceptions are implemented on top of the underlying SEH mechanism, and 
because managed exceptions must interoperate with both SEH and C++ 
exceptions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Windows 
SEH&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Since 
it’s at the base of all exception handling on Windows, let’s look at SEH 
first.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As far as I know, the 
definitive explanation of SEH is still Matt Pietrek’s excellent 1997 article for 
Microsoft Systems Journal: &lt;/FONT&gt;&lt;A 
href="http://www.microsoft.com/msj/0197/exception/exception.aspx"&gt;&lt;FONT 
face=Tahoma 
size=2&gt;http://www.microsoft.com/msj/0197/exception/exception.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There have 
been some extensions since then, like vectored exception handlers, some security 
enhancements, and the new mechanisms to support IA64 and AMD64.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(It’s hard to base exceptions on FS:[0] 
chains if your processor doesn’t have an FS segment register).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ll look at all these changes 
shortly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But Matt’s 1997 article 
remains a goldmine of information.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In fact, it was very useful to the developers who implemented exceptions 
in the CLR.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The SEH 
model is exposed by MSVC via two constructs:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN 
  style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;__try {…} 
  __except(filter_expression) {…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN 
  style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;__try {…} __finally 
  {…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Matt’s 
article explains how the underlying mechanism of two passes over a chain of 
single callbacks is used to provide try/except/finally semantics.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Briefly, the OS dispatches an exception 
by retrieving the head of the SEH chain from TLS.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since the head of this chain is at the 
top of the TIB/TEB (Thread Information Block / Thread Environment Block, 
depending on the OS and the header file you look at), and since the FS segment 
register provides fast access to this TLS block on X86, the SEH chain is often 
called the FS:[0] chain.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Each 
entry consists of a next or a prev pointer (depending on how you look at it) and 
a callback function.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can add 
whatever data you like after that standard entry header.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The callback function is called with all 
sorts of additional information related to the exception that’s being 
processed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This includes the 
exception record and the register state of the machine which was captured at the 
time of the exception.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;To 
implement the 1&lt;SUP&gt;st&lt;/SUP&gt; form of MSVC SEH above (__try/__except), the 
callback evaluates the filter expression during the first pass over the handler 
chain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As exposed by MSVC, the 
filter expression can result in one of three legal values:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;EXCEPTION_CONTINUE_EXECUTION 
= -1&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;EXCEPTION_CONTINUE_SEARCH = 
false 0&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;EXCEPTION_EXECUTE_HANDLER = 
true 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, the filter could also throw its own exception.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s not generally desirable, and I’ll 
discuss that possibility and other flow control issues later.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But if 
you look at the underlying SEH mechanism, the handler actually returns an 
EXCEPTION_DISPOSITION:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;typedef enum 
_EXCEPTION_DISPOSITION&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT 
size=2&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;ExceptionContinueExecution,&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;ExceptionContinueSearch,&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;ExceptionNestedException,&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;ExceptionCollidedUnwind&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;} 
EXCEPTION_DISPOSITION;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So 
there’s some mapping that MSVC is performing here.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Part of that mapping is just a trivial 
conversion between the MSVC filter values and the SEH handler values.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance ExceptionContinueSearch has 
the value 1 at the SEH handler level but the equivalent 
EXCEPTION_CONTINUE_SEARCH has the value 0 at the MSVC filter level.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ouch.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But the 
other part of the mapping has to do with a difference in functionality.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, ExceptionNestedException 
and ExceptionCollidedUnwind are primarily used by the OS dispatch mechanism 
itself.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ll see the circumstances 
in which they arise later.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;More 
importantly, MSVC filters can indicate that the __except clause should run by 
returning EXCEPTION_EXECUTE_HANDLER.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But we shall see that at the SEH level this decision is achieved by 
having the exception dispatch routine fix up the register context and then 
resuming execution at the right spot.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
EXCEPTION_CONTINUE_EXECUTION case supports a rather esoteric use of SEH.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This return value allows the filter to 
correct the problem that caused the exception and to resume execution at the 
faulting instruction.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, 
an application might be watching to see when segments are being written to so 
that it can log this information.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This could be achieved by marking the segment as ReadOnly and waiting for 
an exception to occur on first write.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Then the filter could use VirtualProtect to change the segment containing 
the faulting address to ReadWrite and then restart the faulting 
instruction.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Alternatively, the 
application could have two VirtualAllocs for each region of memory.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One of these could be marked as ReadOnly 
and the second could be a shadow that is marked as ReadWrite.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now the exception filter can simply 
change the register state of the CPU that faulted, so that the register 
containing the faulting address is changed from the ReadOnly segment to the 
shadowed ReadWrite segment.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Obviously anyone who is playing these games must have a lot of 
sophistication and a deep knowledge of how the program executes.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some of these games work better if you 
can constrain the code that’s generated by your program to only touch faulting 
memory using a predictable cliché like offsets from a particular 
register.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I’ll 
talk about this kind of restartable or resumable exception in the context of 
managed code later.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For now, let’s 
pretend that the filter either returns “true – I would like my ‘except’ clause 
to handle this exception” or “false – my ‘except’ clause is uninterested in this 
exception”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the filter returns 
false, the next SEH handler is fetched from the chain and it is asked this same 
question.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The OS 
is pretty paranoid about corrupt stacks during this chain traversal.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It checks that all chain entries are 
within the bounds of the stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;(These bounds are also recorded in the TEB).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OS also checks that all entries are 
in ascending order on the stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 
you violate these rules, the OS will consider the stack to be corrupt and will 
be unable to process exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This is one of the reasons that a Win32 application cannot break its 
stack into multiple disjoint segments as an innovative technique for dealing 
with stack overflow.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
eventually a handler says “true – I would like my ‘except’ clause to handle this 
exception”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because there’s 
a backstop entry at the end of the chain which is placed there by the OS when 
the thread is created.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This last 
entry wants to handle all the exceptions, even if your application-level 
handlers never do.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s where you 
get the default OS behavior of consulting the unhandled exception filter list, 
throwing up dialog boxes for Terminate or Debug, etc.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;As soon 
as a filter indicates that it wants to handle an exception, the first pass of 
exception handling finishes and the second pass begins.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As Matt’s article explains, the handler 
can use the poorly documented RtlUnwind service to deliver second pass 
notifications to all the previous handlers and pop them off the handler 
chain.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In other 
words, no unwinding happened as the first pass progressed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But during the second pass we see two 
distinct forms of unwind.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The first 
form involves popping SEH records from the chain that was threaded from 
TLS.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each such SEH record is popped 
before the corresponding handler gets called for the second pass.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This leaves the SEH chain in a 
reasonable form for any nested exceptions that might occur within a 
handler.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
other form of unwind is the actual popping of the CPU stack.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This doesn’t happen as eagerly as the 
popping of the SEH records.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On X86, 
EBP is used as the frame pointer for methods containing SEH.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;ESP points to the top of the stack, as 
always.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Until the stack is actually 
unwound, all the handlers are executed on top of the faulting exception 
frame.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So the stack actually grows 
when a handler is called for the first or second pass.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;EBP is set to the frame of the method 
containing a filter or finally clause so that local variables of that method 
will be in scope.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
actual popping of the stack doesn’t occur until the catching ‘except’ clause is 
executed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So we’ve 
got a handler whose filter announced in the first pass that it would handle this 
exception via EXCEPTION_EXECUTE_HANDLER.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And that handler has driven the second pass by unwinding and delivering 
all the second pass notifications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Typically it will then fiddle with the register state in the exception 
context and resume execution at the top of the appropriate ‘except’ clause.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This isn’t necessarily the case, and 
later we’ll see some situations where the exception propagation gets 
diverted.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;How 
about the try/finally form of SEH?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Well, it’s built on the same underlying notion of a chain of 
callbacks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;During the first pass 
(the one where the filters execute, to decide which except block is going to 
catch), the finally handlers all say EXCEPTION_CONTINUE_SEARCH.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They never actually catch anything.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then in the second pass, they execute 
their finally blocks.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Subsequent 
additions to SEH&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;All of 
the above – and a lot more – is in Matt’s article.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are a few things that aren’t in 
his article because they were added to the model later.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For 
example, Windows XP introduced the notion of a vectored exception handler.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This allows the application to register 
for a first crack at an exception, without having to wait for exception handling 
to propagate down the stack to an embedded handler.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fortunately, Matt wrote an “Under The 
Hood” article on this particular topic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This can be found at &lt;/FONT&gt;&lt;A 
href="http://msdn.microsoft.com/msdnmag/issues/01/09/hood/default.aspx"&gt;&lt;FONT 
face=Tahoma 
size=2&gt;http://msdn.microsoft.com/msdnmag/issues/01/09/hood/default.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Another 
change to SEH is related to security.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Buffer overruns – whether on the stack or in heap blocks – remain a 
favorite attack vector for hackers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;A typical buffer overrun attack is to pass a large string as an argument 
to an API.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that API expected a 
shorter string, it might have a local on the stack like “char 
filename[256];”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now if the API is 
foolish enough to strcpy a malicious hacker’s argument into that buffer, then 
the hacker can put some fairly arbitrary data onto the stack at addresses higher 
(further back on the stack) than that ‘filename’ buffer.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If those higher locations are supposed 
to contain call return addresses, the hacker may be able to get the CPU to 
transfer execution into the buffer itself.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Oops.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The hacker is 
injecting arbitrary code and then executing it, potentially inside someone 
else’s process or under their security credentials.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There’s 
a new speed bump that an application can use to reduce the likelihood of a 
successful stack-based buffer overrun attack.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This involves the /GS C++ compiler 
switch, which uses a cookie check in the function epilog to determine whether a 
buffer overrun has corrupted the return address before executing a return based 
on its value.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;However, 
the return address trick is only one way to exploit buffer overruns.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve already seen that SEH records are 
necessarily built on the stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And 
in fact the OS actually checks to be sure they are within the stack bounds.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Those SEH records contain callback 
pointers which the OS will invoke if an exception occurs.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So another way to exploit a buffer 
overrun is to rewrite the callback pointer in an SEH record on the stack.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There’s a new linker switch (/SAFESEH) 
that can provide its own speed bump against this sort of attack.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Modules built this way declare that all 
their handlers are embedded in a table in the image; they do not point to 
arbitrary code sequences sprinkled in the stack or in heap blocks.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;During exception processing, the 
exception callbacks can be validated against this table.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, the first and best line of defense against all these attacks is to never 
overrun a buffer.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you are 
writing in managed code, this is usually pretty easy.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You cannot create a buffer overrun in 
managed code unless the CLR contains a bug or you perform unsafe operations 
(e.g. unverifiable MC++ or ‘unsafe’ in C#) or you use high-privilege unsafe APIs 
like StructureToPtr or the various overloads of Copy in the 
System.Runtime.InteropServices.Marshal class.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So, not 
surprisingly and not just for this reason, I recommend writing in managed 
code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if you must write some 
unmanaged code, you should seriously consider using a String abstraction that 
eliminates all those by-rote opportunities for error.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if you must code each strcpy 
individually, be sure to use strncpy instead!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;A final 
interesting change to the OS SEH model since Matt’s article is due to 
Win64.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Both IA64 and AMD64 have a 
model for exception handling that avoids reliance on an explicit handler chain 
that starts in TLS and is threaded through the stack.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, exception handling relies on 
the fact that on 64-bit systems we can perfectly unwind a stack.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And this ability is itself due to the 
fact that these chips are severely constrained on the calling conventions they 
support.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
look at X86, there are an unbounded number of calling conventions possible.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Sure, there are a few common well-known 
conventions like stdcall, cdecl, thiscall and fastcall.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But optimizing compilers can invent 
custom calling conventions based on inter-procedural analysis.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And developers writing in assembly 
language can make novel decisions about which registers to preserve vs. scratch, 
how to use the floating point stack, how to encode structs into registers, 
whether to back-propagate results by re-using the stack that contained in-bound 
arguments, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Within the CLR, we 
have places where we even unbalance the stack by encoding data after a CALL 
instruction, which is then addressable via the return address.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a particularly dangerous game 
because it upsets the branch prediction code of the CPU and can cause prediction 
misses on several subsequent RET instructions.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we are careful to reserve this 
technique for low frequency call paths.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And we also have some stubs that compute indirect JMPs to out-of-line RET 
‘n’ instructions in order to rebalance the stack.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;It would 
be impossible for a stack crawler to successfully unwind these bizarre stacks 
for exception purposes, without completely simulating arbitrary code 
execution.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So on X86 the exception 
mechanism must rely on the existence of a chain of crawlable FS:[0] handlers 
that is explicitly maintained.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Incidentally, the above distinction between perfect stack crawling on 
64-bit systems vs. hopeless stack crawling on X86 systems has deeper 
repercussions for the CLR than just exception handling.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR needs the ability to crawl all 
the managed portions of a thread’s stack on all architectures.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a requirement for proper 
enforcement of Code Access Security; for accurate reporting of managed 
references to the GC; for hijacking return addresses in order to asynchronously 
take control of threads; and for various other reasons.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On X86, the CLR devotes considerable 
resources to achieving this.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
on 64-bit systems the correspondence between an activation record on the stack 
and the exception record that applies to it is not achieved through an FS:[0] 
chain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, unwinding of the 
stack reveals the code addresses that correspond to a particular activation 
record.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These instruction pointers 
of the method are looked up in a table to find out whether there are any 
__try/__except/__finally clauses that cover these code addresses.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This table also indicates how to proceed 
with the unwind by describing the actions of the method epilog.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Managed 
Exceptions&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Okay, 
enough about SEH – for now.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s 
switch to the managed exception model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This model contains a number of constructs.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Depending on the language you code in, 
you probably only have access to a subset of these.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} finally 
{…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
pretty standard.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All managed 
languages should expose this, and it should be the most common style of 
exception handling in user code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of 
course, in the case of MC++ the semantics of ‘finally’ is exposed through 
auto-destructed stack objects rather than through explicit finally clauses.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You should be using ‘finally’ clauses to 
guarantee consistency of application state far more frequently than you use 
‘catch’ clauses.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because 
catch clauses increase the likelihood that developers will swallow exceptions 
that should be handled elsewhere, or perhaps should even be left unhandled.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if catch clauses don’t actually 
swallow an exception (i.e. they ‘rethrow’), they still create a poor debugging 
experience as we shall see.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} catch (Object o) 
{…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
pretty standard, too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One thing 
that might surprise some developers is that you can catch any instance that’s of 
type Object or derived from Object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;However, there is a CLS rule that only subtypes of System.Exception 
should be thrown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, C# is so 
eager for you to only deal with System.Exception that it doesn’t provide any 
access to the thrown object unless you are catching Exception or one of its 
subtypes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When you 
consider that only Exception and its subtypes have support for stack traces, 
HRESULT mapping, standard access to exception messages, and good support 
throughout the frameworks, then it’s pretty clear that you should restrict 
yourself to throwing and processing exceptions that derive from 
Exception.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In 
retrospect, perhaps we should have limited exception support to Exception rather 
than Object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Originally, we wanted 
the CLR to be a useful execution engine for more run-time libraries than just 
the .NET Frameworks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We imagined 
that different languages would execute on the CLR with their own particular 
run-time libraries.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we didn’t 
want to couple the base engine operations too tightly with CLS rules and 
constructs in the frameworks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of 
course, now we understand that the commonality of the shared framework classes 
is a huge part of the value proposition of our managed environment.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I suspect we would revisit our original 
design if we still could.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: Tahoma"&gt;try 
{&lt;/SPAN&gt;&lt;/B&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;…&lt;/SPAN&gt;&lt;/B&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: Tahoma"&gt;} catch 
(Object o) if (expression) {&lt;/SPAN&gt;&lt;/B&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;…&lt;/SPAN&gt;&lt;/B&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
invented syntax, though I’m told it’s roughly what MC++ is considering.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As far as I know, the only two .NET 
languages that currently support exception filters are VB.NET and – of course – 
ILASM.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(We never build a managed 
construct without exposing it via ILDASM and ILASM in a manner that allows these 
two tools to round-trip between source and binary forms).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;VB.NET 
has sometimes been dismissed as a language that’s exclusively for less 
sophisticated developers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the 
way this language exposes the advanced feature of exception filters is a great 
example of why that position is too simplistic.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, it is true that VB has 
historically done a superb job of providing an approachable toolset and 
language, which has allowed less sophisticated developers to be highly 
productive.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
isn’t this cool:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT 
size=2&gt;Try&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;…try 
statements…&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;Catch e As 
InvalidOperationException When expressionFilter&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;…catch 
statements…&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;End 
Try&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;Of course, at the runtime 
level we cannot separate the test for the exception type expression and the 
filter expression.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We only support 
a bare expression.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So the VB 
compiler turns the above catch into&lt;/SPAN&gt; &lt;SPAN 
style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;something like&lt;/SPAN&gt; &lt;SPAN 
style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;this, where $exception_obj is the 
implicit argument passed to the filter.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;Catch When 
(IsInst($exception_obj, InvalidOperationException)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&amp;amp;&amp;amp; expressionFilter)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;While 
we’re on the topic of exception handling in VB, have you ever wondered how VB 
.NET implements its On Error statement?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;On Error { Goto { 
&amp;lt;line&amp;gt; | 0 | -1 } | Resume Next }&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Me 
neither.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But I think it’s pretty 
obvious how to implement this sort of thing with an interpreter.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You wait for something to go wrong, and 
then you consult the active “On Error” setting.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If it tells you to “Resume Next”, you 
simply scan forwards to the next statement and away you go.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But in 
an SEH world, it’s a little more complicated.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I tried some simple test cases with the 
VB 7.1 compiler.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The resulting 
codegen is based on advancing a _Vb_t_CurrentStatement local variable to 
indicate the progression of execution through the statements.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A single try/filter/catch covers 
execution of these statements.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It 
was interesting to see that the ‘On Error’ command only applies to exceptions 
that derive from System.Exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The filter refuses to process any other exceptions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So VB is 
nicely covered.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But what if you did 
need to use exception filters from C#?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Well, in V1 and V1.1, this would be quite difficult.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But C# has announced a feature for their 
next release called anonymous methods.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This is a compiler feature that involves no CLR changes.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It allows blocks of code to be mentioned 
inline via a delegate.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This 
relieves the developer from the tedium of defining explicit methods and state 
objects that can be gathered into the delegate and the explicit sharing of this 
state.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This and other seductive 
upcoming C# features are described at &lt;/FONT&gt;&lt;A 
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbconcprogramminglanguagefuturefeatures.asp"&gt;&lt;FONT 
face=Tahoma 
size=2&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbconcprogramminglanguagefuturefeatures.asp&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Using a 
mechanism like this, someone has pointed out that one could define delegates for 
try, filter and catch clauses and pass them to a shared chunk of ILASM.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I love the way the C# compiler uses type 
inferencing to automatically deduce the delegate types.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it manufactures a state object to 
ensure that the locals and arguments of DoTryCatch are available to the “try 
statements”, “filter expression” and “catch statements”, almost as if everything 
was scoped in a single method body.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;(I say “almost” because any locals or arguments that are of byref, 
argiterator or typedbyref types cannot be disassociated from a stack without 
breaking safety.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So these cases are 
disallowed). &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I’m 
guessing that access to filters from C# could look something like 
this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;public void delegate 
__Try();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;public Int32 delegate 
__Filter();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;public void delegate 
__Catch();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&lt;FONT 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;// this reusable helper would 
be defined in ILASM or VB.NET:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;void DoTryCatch(__Try t, 
__Filter f, __Catch c)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&lt;FONT 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;// And C# could then use it 
as follows:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;void 
m(…arguments…)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT 
size=2&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;…locals…&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;DoTryCatch(&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{ …try 
statements…},&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{ return 
filter_expression; },&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{ …catch 
statements…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT 
size=2&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;You may 
notice that I cheated a little bit.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;I didn’t provide a way for the ‘catch’ clause to mention the exception 
type that it is catching.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of 
course, this could be expressed as part of the filter, but that’s not really 
playing fair.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I suspect the 
solution is to make DoTryCatch a generic method that has an unbound Type 
parameter.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then DoTryCatch&amp;lt;T&amp;gt; 
could be instantiated for a particular type.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, I haven’t actually tried this 
so I hate to pretend that it would work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;I am way behind on understanding what we can and cannot do with generics 
in our next release, how to express this in ILASM, and how it actually works 
under the covers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any blog on that 
topic is years away.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;While we 
are on the subject of interesting C# codegen, that same document on upcoming 
features also discusses iterators.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;These allow you to use the ‘yield’ statement to convert the normal pull 
model of defining iteration into a convenient push model.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can see the same ‘yield’ notion in 
Ruby.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I’m told that both 
languages have borrowed this from CLU, which pioneered the feature about the 
time that I was born.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When you 
get your hands on an updated C# compiler that supports this handy construct, be 
sure to ILDASM your program and see how it’s achieved.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s a great example of what a compiler 
can do to make life easier for a developer, so long as we’re willing to burn a 
few more cycles compared to a more prosaic loop construct.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In today’s world, this is &lt;I 
style="mso-bidi-font-style: normal"&gt;almost&lt;/I&gt; always a sensible 
trade-off.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Okay, 
that last part has nothing to do with exceptions, does it?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s get back to the managed exception 
model.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} fault 
{…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Have you 
ever written code like this, to restrict execution of your finally clause to 
just the exceptional cases?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;bool exceptional = 
true;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try 
{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;…body of 
try…&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;exceptional = 
false;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;} finally 
{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;if (exceptional) 
{…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT 
size=2&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&lt;FONT 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Or how 
about a catch with a rethrow, as an alternate technique for achieving finally 
behavior for just the exceptional cases:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&lt;FONT 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try 
{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;…&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;} catch 
{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;…&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;rethrow;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT 
size=2&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In each 
case, you are accommodating for the fact that your language doesn’t expose fault 
blocks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, I think the only 
language that exposes these is ILASM.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;A fault block is simply a finally clause that only executes in the 
exceptional case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It never executes 
in the non-exceptional case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Incidentally, the first alternative is preferable to the second.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The second approach terminates the first 
pass of exception handling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is 
a fundamentally different semantics, which has a substantial impact on debugging 
and other operations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s look at 
rethrow in more detail, to see why this is the case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Rethrow, 
restartable exceptions, debugging&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Gee, my 
language has rethrow, but no filter.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Why can’t I just treat the following constructs as equivalent?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} filter (expression) 
catch (Exception e) {…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} catch (Exception e) { 
if (!expression) rethrow; …}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In fact, 
‘rethrow’ tries hard to create the illusion that the initial exception handling 
is still in progress.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It uses the 
same exception object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it 
augments the stack trace associated with that exception object, so that it 
includes the portion of stack from the rethrow to the eventual catch.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Hmm, I 
guess I should have already mentioned that the stack trace of an Exception is 
intentionally restricted to the segment of stack from the throw to the 
catch.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We do this for performance 
reasons, since part of the cost of an exception is linear with the depth of the 
stack that we capture.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ll talk 
about the implications of exception performance later.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, you can use the 
System.Diagnostics.StackTrace class to gather the rest of the stack from the 
point of the catch, and then manually merge it into the stack trace from the 
Exception object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But this is a 
little clumsy and we have sometimes been asked to provide a helper to make this 
more convenient and less brittle to changes in the formatting of stack 
traces.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Incidentally, when you are playing around with stack traces (whether they 
are associated with exceptions, debugging, or explicit use of the StackTrace 
class), you will always find JIT inlining getting in your way.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can try to defeat the JIT inliner 
through use of indirected calls like function pointers, virtual methods, 
interface calls and delegates.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or 
you can make the called method “interesting” enough that the JIT decides it 
would be unproductive or too difficult to inline.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All these techniques are flawed, and all 
of them will fail over time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
correct way to control inlining is to use the 
MethodImpl(MethodImplOptions.NoInlining) pseudo-custom attribute from the 
System.Runtime.CompilerServices namespace.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One way 
that a rethrow differs from a filter is with respect to resumable or restartable 
exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve already seen how 
SEH allows an exception filter to return EXCEPTION_CONTINUE_EXECUTION.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This causes the faulting instruction to 
be restarted.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously it’s 
unproductive to do this unless the filter has first taken care of the faulting 
situation somehow.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It could do this 
by changing the register state in the exception context so that a different 
value is dereferenced, or so that execution resumes at a different 
instruction.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it could have 
modified the environment the program is running in, as with the VirtualProtect 
cases that I mentioned earlier.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In V1 
and V1.1, the managed exception model does not support restartable 
exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, I think that 
we set EXCEPTION_NONCONTINUABLE on some (but perhaps not all) of our exceptions 
to indicate this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are several 
reasons why we don’t support restartable exceptions:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l8 level1 lfo9"&gt;&lt;FONT 
  face=Tahoma size=2&gt;In order to repair a faulting situation, the exception 
  handler needs intimate knowledge about the execution environment.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In managed code, we’ve gone to great 
  lengths to hide these details.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;For example, there is no architecture-neutral mapping from the IL 
  expression of stack-based execution to the register set of the underlying 
  CPU.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l8 level1 lfo9"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Restartability is often desired for asynchronous 
  exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By ‘asynchronous’ I 
  mean that the exception is not initiated by an explicit call to ‘throw’ in the 
  code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rather, it results from a 
  memory fault or an injected failure like Abort that can happen on any 
  instruction.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Propagating a 
  managed exception, where this involves execution of a managed filter, 
  necessarily involves the potential for a GC.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A JIT has some discretion over the 
  GC-safe points that it chooses to support in a method.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Certainly the JIT must gather GC 
  information to report roots accurately at all call-sites.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the JIT normally isn’t required to 
  maintain GC info for every instruction.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;If any instruction might fault, and if any such fault could be resumed, 
  then the JIT would need GC info for all instructions in all methods.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would be expensive.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, ‘mov eax, ecx’ cannot fault 
  due to memory access issues.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
  a surprising number of instructions are subject to fault if you consider all 
  of memory – including the stack – to be unmapped.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And even ‘mov eax, ecx’ can fault due 
  to a Thread.Abort.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
were paying attention to that last bullet, you might be wondering how 
asynchronous exceptions could avoid GC corruption even without resumption.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After all, the managed filter will still 
execute and we know that the JIT doesn’t have complete GC information for the 
faulting instruction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Our 
current solution to this on X86 is rather ad hoc, but it does work.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, we constrain the JIT to never 
flow the contents of the scratch registers between a ‘try’ clause and any of the 
exception clauses (‘filter’, ‘finally’, ‘fault’ and ‘catch’).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The scratch registers in this case are 
EAX, ECX, EDX and sometimes EBP.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Our JIT compiler decides, method-by-method, whether to use EBP as a 
stack-frame register or a scratch register.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, EBP isn’t really a scratch 
register since callees will preserve it for us, but you can see where I’m 
going.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Now when 
an asynchronous exception occurs, we can discard the state of all the scratch 
registers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of EAX, ECX 
&amp;amp; EDX, we can unconditionally zero them in the register context that is 
flowed via exception propagation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In the case of EBP, we only zero it if we aren’t using EBP as a frame 
register.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we execute a managed 
handler, we can now report GC roots based on the GC information that’s 
associated with the handler’s instruction pointer.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
downside to this approach, other than its ad hoc nature, is that it constrains 
the codegen of any method that contains exception handlers.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At some point we may have to model 
asynchronous exceptions more accurately, or expand the GC information spewed by 
the JIT compiler, or a combination, so that we can enable better code generation 
in the presence of exceptions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We’ve 
already seen how VB.NET can use a filter and explicit logic flow from a catch 
clause to create the illusion of restartable exceptions to support ‘On Error 
Resume Next’.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But this should not 
be confused with true restartability.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Before 
we leave the topic of rethrow, we should briefly consider the InnerException 
property of System.Exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This 
allows one exception to be wrapped up in the state of another exception.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A couple of important places where we 
take advantage of this are reflection and class construction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When you 
perform late-bound invocation via reflection (e.g. Type.InvokeMember or 
MethodInfo.Invoke), exceptions can occur in two places:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l6 level1 lfo4"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The reflection infrastructure may 
decide that it cannot satisfy your request, perhaps because you passed the wrong 
number of arguments, or the member lookup failed, or you are invoking on someone 
else’s private members.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That last 
one sounds vaguely dirty.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l6 level1 lfo4"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The late-bound invocation might 
work perfectly, but the target method you called may throw an exception back at 
you.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Reflection must faithfully 
give you that exception as the result of the call.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Returning it as an outbound argument, 
rather than throwing it at you, would be dangerous.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We would lose one of the wonderful 
properties of exceptions, which is that they are hard to ignore.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Error codes are constantly being 
swallowed or otherwise ignored, leading to fragile execution.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
problem is that these two sources of exceptions are ambiguous.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There must be some way to tell whether 
the invocation attempt failed or whether the target of the invocation 
failed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Reflection 
disambiguates these cases by using an instance of 
System.Reflection.TargetInvocationException for the case where the invoked 
method threw an exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
InnerException property of this instance is the exception that was thrown by the 
invoked method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you get any 
exceptions from a late-bound invocation other than TargetInvocationException, 
those other exceptions indicate problems with the late-bound dispatch attempt 
itself.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Something similar happens with TypeInitializationException.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a class constructor (.cctor) method 
fails, we capture that exception as the InnerException of a 
TypeInitializationException.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Subsequent attempts to use that class in this AppDomain from this or 
other threads will have that same TypeInitializationException instance thrown at 
them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So 
what’s the difference between the following three constructs, where the 
overloaded constructor for MyExcep is placing its argument into 
InnerException:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} catch (Exception e) { 
if (expr) rethrow; …}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} catch (Exception e) { 
if (expr) throw new MyExcep(); …}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;try {…} catch (Exception e) { 
if (expr) throw new MyExcep(e); …}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Well, 
the 2&lt;SUP&gt;nd&lt;/SUP&gt; form is losing information.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The original exception has been 
lost.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s hard to recommend that 
approach.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Between 
the 1&lt;SUP&gt;st&lt;/SUP&gt; and 3&lt;SUP&gt;rd&lt;/SUP&gt; forms, I suppose it depends on whether the 
intermediary can add important information by wrapping the original exception in 
a MyExcep instance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if you are 
adding value with MyExcep, it’s still important to preserve the original 
exception information in the InnerException so that sophisticated programs and 
developers can determine the complete cause of the error.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Probably 
the biggest impact from terminating the first pass of exception handling early, 
as with the examples above, is on debugging.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Have you ever attached a debugger to a 
process that has failed with an unhandled exception?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When everything goes perfectly, the 
debugger pops up sitting in the context of the RaiseException or trap 
condition.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;That’s 
so much better than attaching the debugger and ending up on a ‘rethrow’ 
statement.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What you really care 
about is the state of the process when the initial exception was thrown.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the first pass has terminated and 
the original state of the world may have been lost.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s clear why this happens, based on 
the two pass nature of exception handling.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Actually, the determination of whether or not the original state of the 
world has been lost or merely obscured is rather subtle.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Certainly the current instruction 
pointer is sitting in the rethrow rather than on the original fault.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But remember how filter and finally 
clauses are executed with an EBP that puts the containing method’s locals in 
scope… and an ESP that still contains the original faulting method?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It turns out that the catching handler 
has some discretion on whether to pop ESP before executing the catch clause or 
instead to delay the pop until the catch clause is complete.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The managed handler currently pops the 
stack before calling the catch clause, so the original state of the exception is 
truly lost.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I believe the unmanaged 
C++ handler delays the pop until the catch completes, so recovering the state of 
the world for the original exception is tricky but possible.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Regardless, every time you catch and rethrow, you inflict this bitter 
disappointment on everyone who debugs through your code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, there are a number of 
places in managed code where this disappointment is unavoidable.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The most 
unfortunate place is at AppDomain boundaries.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ve already explained at &lt;/FONT&gt;&lt;A 
href="http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/56dd7611-a199-4a1f-adae-6fac4019f11b"&gt;&lt;FONT 
face=Tahoma 
size=2&gt;http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/56dd7611-a199-4a1f-adae-6fac4019f11b&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt; why the Isolation requirement of AppDomains forces us to 
marshal most exceptions across the boundary.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we’ve just discussed how reflection 
and class construction terminate the first pass by wrapping exceptions as the 
InnerException of an outer exception.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One 
alternative is to trap on all first-chance exceptions.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because debuggers can have first 
crack at exceptions before the vectored exception handler even sees the 
fault.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This certainly gives you the 
ability to debug each exception in the context in which it was thrown.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But you are likely to see a lot of 
exceptions in the debugger this way!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In fact, 
throughout V1 of the runtime, the ASP.NET team ran all their stress suites with 
a debugger attached and configured to trap on first-chance Access Violations 
(“sxe av”).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Normally an AV in 
managed code is converted to a NullReferenceException and then handled like any 
other managed exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
ASP.NET’s settings caused stress to trap in the debugger for any such AV.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So their team enforced a rule that all 
their suites (including all dependencies throughout FX) must avoid such 
faults.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;It’s an 
approach that worked for them, but it’s hard to see it working more 
broadly.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Instead, 
over time we need to add new hooks to our debuggers so they can trap on just the 
exceptions you care about.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This 
might involve trapping exceptions that are escaping your code or are being 
propagated into your code (for some definition of ‘your code’).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it might involve trapping exceptions 
that escape an AppDomain or that are propagated into an AppDomain.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
above text has described a pretty complete managed exception model.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But there’s one feature that’s 
conspicuously absent.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There’s no 
way for an API to document the legal set of exceptions that can escape from 
it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some languages, like C++, 
support this feature.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Other 
languages, like Java, mandate it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Of course, you could attach Custom Attributes to your methods to indicate 
the anticipated exceptions, but the CLR would not enforce this.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It would be an opt-in discipline that 
would be of dubious value without global buy-in and guaranteed 
enforcement.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
another of those religious language debates.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I don’t want to rehash all the reasons 
for and against documenting thrown exceptions.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I personally don’t believe the 
discipline is worth it, but I don’t expect to change the minds of any 
proponents.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It doesn’t 
matter.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;What 
does matter is that disciplines like this must be applied universally to have 
any value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we either need to 
dictate that everyone follow the discipline or we must so weaken it that it is 
worthless even for proponents of it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And since one of our goals is high productivity, we aren’t going to 
inflict a discipline on people who don’t believe in it – particularly when that 
discipline is of debatable value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;(It is debatable in the literal sense, since there are many people on 
both sides of the argument).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;To me, 
this is rather like ‘const’ in C++.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;People often ask why we haven’t bought into this notion and applied it 
broadly throughout the managed programming model and frameworks.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once again, ‘const’ is a religious 
issue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some developers are fierce 
proponents of it and others find that the modest benefit doesn’t justify the 
enormous burden.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And, once again, 
it must be applied broadly to have value.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Now in 
C++ it’s possible to ‘const-ify’ the low level runtime library and services, and 
then allow client code to opt-in or not.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And when the client code runs into places where it must lose ‘const’ in 
order to call some non-const-ified code, it can simply remove ‘const’ via a 
dirty cast.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have all done this 
trick, and it is one reason that I’m not particularly in favor of ‘const’ 
either.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But in a 
managed world, ‘const’ would only have value if it were enforced by the 
CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That means the verifier would 
prevent you from losing ‘const’ unless you explicitly broke type safety and were 
trusted by the security system to do so.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Until more than 80% of developers are clamoring for an enforced ‘const’ 
model throughout the managed environment, you aren’t going to see us added 
it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Foray into 
C++ Exceptions&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;C++ 
exposes its own exception model, which is distinct from the __try / __except / 
__finally exposure of SEH.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is 
done through auto-destruction of stack-allocated objects and through the ‘try’ 
and ‘catch’ keywords.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that 
there are no double-underbars and there is no support for filters other than 
through matching of exception types.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Of course, under the covers it’s still SEH.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So there’s still an FS:[0] handler (on 
X86).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the C++ compiler 
optimizes this by only emitting a single SEH handler per method regardless of 
how many try/catch/finally clauses you use.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The compiler emits a table to indicate 
to a common service in the C-runtime library where the various try, catch and 
finally clauses can be found in the method body.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, one of the biggest differences between SEH and the C++ exception model 
is that C++ allows you to throw and catch objects of types defined in your 
application.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SEH only lets you 
throw 32-bit exception codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You 
can use _set_se_translator to map SEH codes into the appropriate C++ classes in 
your application.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;A large 
part of the C++ exception model is implicit.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rather than use explicit try / finally / 
catch clauses, this language encourages use of auto-destructed local 
variables.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whether the method 
unwinds via a non-exceptional return statement or an exception being thrown, 
that local object will auto-destruct.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
basically a ‘finally’ clause that’s been wrapped up in a more useful language 
construct.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Auto-destruction occurs 
during the second pass of SEH, as you would expect.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Have you 
noticed that the C++ exception you throw is often a stack-allocated local?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And that if you explicitly catch it, 
this catch is also with a stack-allocated object?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Did you ever wake up at night in a cold 
sweat, wondering whether a C++ in-flight exception resides on a piece of stack 
that’s already been popped?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of 
course not.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In fact, 
we’ve now seen enough of SEH to understand how the exception always remains in a 
section of the stack above ESP (i.e. within the bounds of the stack).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Prior to the throw, the exception is 
stack-allocated within the active frame.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;During the first pass of SEH, nothing gets popped.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the filters execute, they are 
pushed deeper on the stack than the throwing frame.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When a 
frame declares it will catch the exception, the second pass starts.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even here, the stack doesn’t 
unwind.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then, before resetting the 
stack pointer, the C++ handler can copy-construct the original exception from 
the piece of stack that will be popped into the activation frame that will be 
uncovered.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
are an expert in unmanaged C++ exceptions, you will probably be interested to 
learn of the differences between managed C++ exceptions and unmanaged C++ 
exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There’s a good write-up 
of these differences at &lt;/FONT&gt;&lt;A 
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmex/html/vccondifferencesinexceptionhandlingbehaviorundermanagedexceptionsforc.asp"&gt;&lt;FONT 
face=Tahoma 
size=2&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmex/html/vccondifferencesinexceptionhandlingbehaviorundermanagedexceptionsforc.asp&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;A Single 
Managed Handler&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We’ve 
already seen how the C++ compiler can emit one SEH handler per method and reuse 
it for all the exception blocks in that method.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The handler can do this by consulting a 
side table that indicates how the various clauses map to instruction sequences 
within that method.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In the 
managed environment, we can take this even further.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We maintain a boundary between managed 
and unmanaged code for many reasons, like synchronization with the garbage 
collector, to enable stack crawling through managed code, and to marshal 
arguments properly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have 
modified this boundary to erect a single SEH handler at every unmanaged -&amp;gt; 
managed call in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For the most part, 
we must do this without compiler support since many of our transitions occur 
through dynamically generated machine code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The cost 
of modifying the SEH chain during calls into managed code is quickly amortized 
as we call freely between managed methods.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;So the immediate cost of pushing FS:[0] handlers on method entry is 
negligible for managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
there is still an impact on the quality of the generated code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We saw part of this impact in the 
discussion of register usage across exception clauses to remain 
GC-safe.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, the biggest cost of exceptions is when you actually throw one.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ll return to this near the end of the 
blog.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Flow 
Control&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Here’s 
an interesting scenario that came up recently.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Let’s 
say we drive the first pass of exception propagation all the way to the end of 
the handler chain and we reach the unhandled exception backstop.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That backstop will probably pop a dialog 
in the first pass, saying that the application has suffered an unhandled 
exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Depending on how the 
system is configured, the dialog may allow us to terminate the process or debug 
it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s say we choose 
Terminate.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Now the 
2&lt;SUP&gt;nd&lt;/SUP&gt; pass begins.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;During 
the 2&lt;SUP&gt;nd&lt;/SUP&gt; pass, all our finally clauses can execute.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;What if 
one of those 2&lt;SUP&gt;nd&lt;/SUP&gt; pass ‘finally’ clauses throws a new exception?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’re going to start a new exception 
propagation from this location – with a new Exception instance.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we drive this new Exception up the 
chain, we may actually find a handler that will swallow the second 
exception.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If this 
is the case, the process won’t terminate due to that first exception. &lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;This is despite the fact that SEH told 
the user we had an unhandled exception, and the user told us to terminate the 
process.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
surprising, to say the least.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And 
this behavior is possible, regardless of whether managed or unmanaged exceptions 
are involved.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The mechanism for SEH 
is well-defined and the exception model operates within those rules.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;An application should avoid certain 
(ab)uses of this mechanism, to avoid confusion.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Indeed, 
we have prohibited some of those questionable uses in managed code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In 
unmanaged, you should never return from a finally.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In an exceptional execution of a 
finally, a return has the effect of terminating the exception processing.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The catch handler never sees its 
2&lt;SUP&gt;nd&lt;/SUP&gt; pass and the exception is effectively swallowed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Conversely, in a non-exceptional 
execution of a finally, a return has the effect of replacing the method’s return 
value with the return value from the finally.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is likely to cause developer 
confusion.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So in 
managed code we’ve made it impossible for you to return from a finally 
clause.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The full rules for flow 
control involving managed exception clauses should be found at Section 12.4.2.8 
of ECMA Partition I (&lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/net/ecma/"&gt;&lt;FONT 
face=Tahoma size=2&gt;http://msdn.microsoft.com/net/ecma/&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;However, 
it is possible to throw from a managed finally clause.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(In general, it’s very hard to 
confidently identify regions of managed code where exceptions cannot be 
thrown).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And this can have the 
effect of replacing the exception that was in flight with a new 1&lt;SUP&gt;st&lt;/SUP&gt; 
and 2&lt;SUP&gt;nd&lt;/SUP&gt; pass sweep, as described above.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the ExceptionCollidedUnwind 
situation that is mentioned in the EXCEPTION_DISPOSITION enumeration.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The C++ 
language takes a different approach to exceptions thrown from the 2&lt;SUP&gt;nd&lt;/SUP&gt; 
pass.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve already seen that C++ 
autodestructors execute during the 2&lt;SUP&gt;nd&lt;/SUP&gt; pass of exception 
handling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you’ve ever thrown an 
exception from the destructor, when that destructor is executed as part of an 
exception unwind, then you have already learned a painful lesson.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The C++ behavior for this situation is 
to terminate the process via a termination handler.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In 
unmanaged C++, this means that developers must follow great discipline in the 
implementation of their destructors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Since eventually those destructors might run in the context of exception 
backout, those destructors should never allow an exception to escape them.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s painful, but presumably 
achievable.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In 
managed C++, I’ve already mentioned that it’s very hard to identify regions 
where exceptions cannot occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
ability to prevent (asynchronous and resource) exceptions over limited ranges of 
code is something we would like to enable at some point in the future, but it 
just isn’t practical in V1 and V1.1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;It’s way too easy for an out-of-memory or type-load or 
class-initialization or thread-abort or appdomain-unload or similar exception to 
intrude.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Finally, 
it’s possible for exceptions to be thrown during execution of a filter.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When this happens in an OS SEH context, 
it results in the ExceptionNestedException situation that is mentioned in the 
EXCEPTION_DISPOSITION enumeration.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The managed exception model took a different approach here.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve already seen that an MSVC filter 
clause has three legal returns values (resume execution, continue search, and 
execute handler).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a managed 
filter throws an exception, we contain that exception and consider the filter to 
have replied “No, I don’t want to handle this one.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Continue searching for a 
handler”.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
a reasonable interpretation in all cases, but it falls out particularly well for 
stack overflow.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With the historical 
OS support for stack overflow, it’s very hard to reliably execute backout 
code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As I’ve mentioned in other 
blogs, you may only have one 4K page of stack available for this purpose.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you blow that page, the process is 
terminated.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s very hard to 
execute managed filters reliably within such a limited region.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So a reasonable approach is to consider 
the filters to have themselves thrown a StackOverflowException and for us to 
interpret this as “No, I don’t want to handle this one.”&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In a 
future version, we would like to provide a more defensible and useful mechanism 
for handling stack overflow from managed code. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Error 
Handling without Exceptions&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So we’ve 
seen how SEH and C++ and managed exceptions all interoperate.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But not all error handling is based on 
exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we consider 
Windows, there are two other error handling systems that the CLR can 
interoperate with.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These are the 
Get/SetLastError mechanism used by the OS and the HRESULT / IErrorInfo mechanism 
used by COM.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Let’s 
look at the GetLastError mechanism first, because it’s relatively simple.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A number of OS APIs indicate failure by 
returning a sentinel value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Usually 
this sentinel value is -1 or 0 or 1, but the details vary depending on the 
API.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This sentinel value indicates 
that the client can call GetLastError() to recover a more detailed OS status 
code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, it’s sometimes 
hard to know which APIs participate in the GetLastError protocol.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Theoretically this information is always 
documented in MSDN and is consistent from one version of the OS to the next – 
including between the NT and Win95-based OSes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The real 
issue occurs when you PInvoke to one of these methods.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OS API latches any failure codes 
with SetLastError.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now on the 
return path of the PInvoke, we may be calling various OS services and managed 
services to marshal the outbound arguments.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We may be synchronizing with a pending 
GC, which could involve a blocking operation like WaitForSingleObject.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Somewhere in here, we may call another 
OS API that itself latches an error code (or the absence of an error code) 
through its own call to SetLastError.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So by 
the time we return to some managed code that can generate up a new PInvoke stub 
to call GetLastError, you can be sure that the original error code is long 
gone.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The solution is to tag your 
PInvoke declaration to indicate that it should participate in the GetLastError 
protocol.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This tells the PInvoke 
call to capture the error as part of the return path, before any other OS calls 
on this thread have an opportunity to erase it or replace it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This 
protocol works well for PInvokes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Unfortunately, we do not have a way to tag IJW VTFixup stubs in the same 
way.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So when you make managed -&amp;gt; 
unmanaged calls via MC++ IJW, there isn’t a convenient and reliable way to 
recover a detailed OS status code on the return path.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously this is something we would 
like to address in some future version, though without blindly inflicting the 
cost of a GetLastError on all managed -&amp;gt; unmanaged transitions through 
IJW.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;COM Error 
Handling&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;To 
understand how the CLR interoperates with COM HRESULTs, we must first review how 
PreserveSig is used to modify the behavior of PInvoke and COM 
Interop.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Normally, COM signatures return an HRESULT error code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the method needs to communicate some 
other result, this is typically expressed with an [out, retval] outbound 
argument.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, there are 
exceptions to this pattern.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For 
example, IUnknown::AddRef and Release both return a count of the outstanding 
references, rather than an HRESULT.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;More importantly, HRESULTs can be used to communicate success codes as 
well as error codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The two most 
typical success codes are S_OK and S_FALSE, though any HRESULT with the high bit 
reset is considered a success code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;COM 
Interop normally transforms the unmanaged signature to create a managed 
signature where the [out, retval] argument becomes the managed return 
value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If there is no [out, 
retval], then the return type of the managed method is ‘void’.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then the COM Interop layer maps between 
failure HRESULTs and managed exceptions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Here’s a simple example:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;COM:&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/SPAN&gt;HRESULT GetValue([out, retval] IUnknown 
**ppRet)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;CLR:&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/SPAN&gt;IUnknown 
GetValue()&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;However, 
the return value might be a DWORD-sized integer that should not be interpreted 
as an HRESULT.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it might be an 
HRESULT – but one which must sometimes distinguish between different success 
codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In these cases, PreserveSig 
can be specified on the signature and it will be preserved on the managed side 
as the traditional COM signature.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, the same can happen with PInvoke signatures.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Normally a DLL export like Ole32.dll’s 
CoGetMalloc would have its signature faithfully preserved.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Presumably the transformation would be 
something like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;DLL:&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/SPAN&gt;HRESULT CoGetMalloc(DWORD c, [out, 
retval] IMalloc **ppRet)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;CLR:&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/SPAN&gt;DWORD &lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;CoGetMalloc(DWORD c, ref IMalloc 
ppRet)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If OLE32 
returns some sort of failure HRESULT from this call, it will be returned to the 
managed caller.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If instead the 
application would prefer to get this error case automatically converted to a 
managed Exception, it can use PreserveSig to indicate this.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Huh?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the COM case 
PreserveSig means “give me the unconverted HRESULT signature”, but in the 
PInvoke case PreserveSig means “convert my HRESULTs into exceptions.”&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Why would we use the same flag to 
indicate exactly opposite semantics for these two interop layers?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The reasons are, ahem, historical.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The best way to think of PreserveSig is 
“give me the unusual transformation of my signature, as opposed to what is 
typical for the kind of interop I am doing.”&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So now 
we know how to obtain mappings between HRESULTs and managed exceptions for the 
typical COM Interop case (no PreserveSig) and the atypical PInvoke case 
(PreserveSig).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But what are the 
details of that mapping?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
exception subsystem in the CLR has mappings between COM errors, OS errors, and 
managed exception types.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Of 
course, sometimes we have a situation which doesn’t have a precise mapping.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of an HRESULT that isn’t 
associated with a specific managed Exception class, we convert it to an instance 
of COMException.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of an 
OS status code that isn’t associated with a specific managed Exception class, we 
convert it to an instance of SEHException.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Even for 
cases where we have a correspondence between a managed and unmanaged 
representation, the mapping won’t necessarily roundtrip.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For instance, an AV in unmanaged code 
results in an SEH exception of code 0xC0000005.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If this is driven through managed code, 
it will be mapped to the corresponding NullReferenceException class.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the propagation of this exception 
continues through managed code and further up the stack to an unmanaged SEH 
handler, the unmanaged code will see the original exception code of 
0xC0000005.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So, when propagating 
through that sequence of handlers, we see a perfect roundtrip.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But 
let’s change the scenario slightly, so that the original AccessViolation occurs 
in managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now we have a 
NullReferenceException that is being propagated out to an unmanaged SEH handler 
further back on the stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But this 
time the NullReferenceException will be mapped to an SEH exception code of 
0xE0434F4D.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the managed 
exception code used for all managed exceptions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Have you 
ever wondered where these exception codes come from?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well 0xE0434F4D is 0xE0+“COM”.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Originally the CLR was called COM+ 
2.0.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we changed the project 
name, we neglected to change the exception code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The unmanaged C++ exceptions use 
0xE06D7363, which is 0xE0+“msc”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;You might also see 0xE0524F54 for 0xE0+“ROT” on Rotor builds.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
current mapping between OS status codes and managed exception types is quite 
limited.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It contains standard 
transformations like:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_INEXACT_RESULT&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_INVALID_OPERATION&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_STACK_CHECK&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_UNDERFLOW&lt;SPAN 
style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; ArithmeticException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_OVERFLOW&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_INTEGER_OVERFLOW&lt;SPAN 
style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; OverflowException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_DIVIDE_BY_ZERO&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_INTEGER_DIVIDE_BY_ZERO&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;=&amp;gt; 
DivideByZeroException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_FLOAT_DENORMAL_OPERAND&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; FormatException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_ACCESS_VIOLATION&lt;SPAN 
style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; NullReferenceException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_ARRAY_BOUNDS_EXCEEDED&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;=&amp;gt; 
IndexOutOfRangeException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_NO_MEMORY&lt;SPAN 
style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; OutOfMemoryException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;STATUS_STACK_OVERFLOW&lt;SPAN 
style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; StackOverflowException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
HRESULT mappings are far more extensive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;They include standard mappings to the well-known HRESULT values 
like:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;E_POINTER&lt;SPAN 
style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; ArgumentNullException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And they 
include mappings to CLR-defined HRESULTs in the 0x8013???? range that you’ve 
doubtless witnessed during your development and debugging.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The managed platform has its own 
facility code for reserving a range of HRESULTs for our exclusive 
use.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;COR_E_ENTRYPOINTNOTFOUND&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;=&amp;gt; EntryPointNotFoundException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And our 
mappings include a gathering of similar HRESULTs to a single managed 
exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here’s a particularly 
extensive gathering of 26 different HRESULTs to the FileLoadException 
class:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_REF_DEF_MISMATCH&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_INVALID_PRIVATE_ASM_LOCATION&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;COR_E_ASSEMBLYEXPECTED&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_SIGNATURE_CHECK_FAILED&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_ASM_MODULE_MISSING&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_INVALID_NAME&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_PRIVATE_ASM_DISALLOWED&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;COR_E_MODULE_HASH_CHECK_FAILED&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;COR_E_FILELOAD&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;SECURITY_E_INCOMPATIBLE_SHARE&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;SECURITY_E_INCOMPATIBLE_EVIDENCE&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;SECURITY_E_UNVERIFIABLE&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;COR_E_FIXUPSINEXE&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_OPEN_FAILED)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_DISK_CORRUPT)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_UNRECOGNIZED_VOLUME)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_FILE_INVALID)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_DLL_INIT_FAILED)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;FUSION_E_CODE_DOWNLOAD_DISABLED&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;CORSEC_E_MISSING_STRONGNAME&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;INIT_E_DOWNLOAD_FAILURE&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;MSEE_E_ASSEMBLYLOADINPROGRESS&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;=&amp;gt; 
FileLoadException&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There 
are some more observations we can make about the COM error handling 
approach.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, it should be 
obvious that the 32-bits of an HRESULT cannot uniquely define an arbitrary set 
of user-extensible error conditions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;COM deals with this, in part, by including the interface that returns an 
HRESULT in the decision of how to interpret these 32-bits.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that 0xE3021051 returned from 
IMyInterface is not the same error code as 0xE3201051 returned from 
IYourInterface.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, it 
also means that each interface must be rigorous about the bit patterns it 
returns.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Specifically, it would be 
very bad if the implementation of IMyInterface::m() happens to delegate to 
IYourInterface::n() and blindly return ‘n’s HRESULTs.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any HRESULTs returned from ‘n’ must 
somehow be mapped to the bit patterns that are legal to return from 
IMyInterface::m().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If ‘n’ returns a 
bit pattern that IMyInterface::m() cannot map, then ‘m’ is obligated to convert 
the HRESULT to E_UNEXPECTED and return that.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In other 
words, the uniqueness constraint for HRESULTs forces a painful discipline on all 
COM implementations that return HRESULTs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And part of this discipline is to lose error information by mapping 
meaningful HRESULTs into E_UNEXPECTED if the context for interpreting those 
HRESULTs is being lost.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(There is a 
well-defined set of system HRESULTs which are implicitly returnable from any 
interface.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The bit pattern for 
E_UNEXPECTED is necessarily part of this set.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR facility code allows us to live 
in this privileged world with our own codes).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The fact 
that most COM developers are unaware of this painful discipline and don’t follow 
it, just adds to the level of pain here.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Fortunately, COM supplements the limited expressibility and uniqueness of 
HRESULTs by using a second mechanism: IErrorInfo.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And the COM Interop layer uses this 
supplementary mechanism when mapping to and from managed exception objects.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, System.Exception implements the 
IErrorInfo interface.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a 
managed exception is thrown to a COM client, the IErrorInfo of the Exception 
instance is available for the COM client to query.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Adam 
Nathan’s excellent book “.NET and COM – The Complete Interoperability Guide” 
describes how the IErrorInfo state is filled in from a managed exception in 
Chapter 16.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There’s 
one more detail of COM Interop HRESULT mapping that warrants discussion.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s good practice for all COM methods 
to return an HRESULT.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But there are 
several famous violations of this rule, including IUnknown::AddRef and 
Release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;More importantly, every 
developer can choose whether to follow this best practice.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some choose not to.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And there are some typical cases, like 
event sinks, where we often see methods returning ‘void’ or ‘bool’.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This 
presents the COM Interop error mapping layer with a problem.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If an exception occurs inside a managed 
implementation of a method with one of these signatures, it’s hard to convey the 
error information back to the COM caller.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;There are several choices available to that layer – none of them 
good:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l4 level1 lfo5"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Allow the managed exception to 
travel back through the COM caller, using the underlying SEH mechanism.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This would work perfectly, but is 
strictly illegal.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well-behaved COM 
servers do not propagate exceptions out to their COM clients.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l4 level1 lfo5"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Swallow the managed 
exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Propagate a return value 
with ‘0’ out to the COM client.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This 0 value might get interpreted as a returned Boolean, integer, pUnk 
or other data type.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of 
a ‘void’ signature, it will simply be ignored.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l4 level1 lfo5"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;3)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Convert the exception object into 
an HRESULT value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Propagate that 
HRESULT out as the return value to the COM client.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the ‘void’ case, this will again be 
ignored.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the pUnk case, it will 
likely be dereferenced and subsequently cause an AccessViolation.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Failure HRESULTs have the high bit 
set.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On Win32 the high 2 GB of 
address space are reserved for the kernel and are unavailable unless you run a 
/LARGEADDRESSAWARE process on a suitably booted system.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On Win64, the low couple of GB of 
address are reserved and unavailable to detect this sort of mistake).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;As you 
can see, all of these solutions are broken.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, the most broken of the 
three is the last one… and that’s the one we currently follow.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I suspect we will change our behavior 
here at some point.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Until then, we 
rely on the fact that AddRef &amp;amp; Release are specially handled and that the 
other cases are rare and are typically ‘void’ or ‘bool’ returns.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Performance 
and Trends&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Exceptions vs. error codes has always been a controversial topic.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For the last 15 years, every team has 
argued whether their codebase should throw exceptions or return error 
codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Hopefully nobody argues 
whether their team should mix both styles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;That’s never desirable, though it often takes major surgery to migrate to 
a consistent plan.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;With any 
religious controversy, there are many arguments on either side.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some of them are related to:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo6"&gt;&lt;FONT 
  face=Tahoma size=2&gt;A philosophy of what errors mean and whether they should be 
  expressed out-of-band with the method contract.&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo6"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Exceptions have a direct cost when you actually throw and catch an 
  exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They may also have an 
  indirect cost associated with pushing handlers on method entry.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And they can often have an insidious 
  cost by restricting codegen opportunities.&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo6"&gt;&lt;FONT 
  face=Tahoma size=2&gt;It’s relatively easy to forget to check for a returned 
  error code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s much harder to 
  inadvertently swallow an exception without handling it (though we still find 
  developers doing so!)&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo6"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Exceptions tend to capture far more information about the 
  cause and location of an error, though one could envision an error code system 
  that’s equally powerful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;(IErrorInfo anybody?)&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So 
what’s the right answer here?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Well if 
you are building the kernel of an operating system, you should probably use 
error codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You are a programming 
God who rarely makes mistakes, so it’s less likely that you will forget to check 
your return codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And there are 
sound bootstrapping and performance reasons for avoiding exceptions within the 
kernel.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, some of the OS 
folks here think that SEH should be reserved for terrible “take down the 
process” situations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That may have 
been the original design point.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
SEH is such a flexible system, and it is so entrenched as the basis for 
unmanaged C++ exceptions and managed exceptions, that it is no longer reasonable 
to restrict the mechanism to these critical failures.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So, if 
you are not a programming God like those OS developers, you should consider 
using exceptions for your application errors.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They are more powerful, more expressive, 
and less prone to abuse than error codes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;They are one of the fundamental ways that we make managed programming 
more productive and less error prone. &lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;In fact, the CLR internally uses 
exceptions even in the unmanaged portions of the engine.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, there is a serious long term 
performance problem with exceptions and this must be factored into your 
decision.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Consider 
some of the things that happen when you throw an exception:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l3 level1 lfo7"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Grab a stack trace by interpreting metadata emitted by the 
  compiler to guide our stack unwind.&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l3 level1 lfo7"&gt;&lt;FONT 
  size=2&gt;&lt;FONT face=Tahoma&gt;Run through a chain of handlers up the stack, calling 
  each handler twice.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l3 level1 lfo7"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Compensate for mismatches between SEH, C++ and managed 
  exceptions.&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l3 level1 lfo7"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Allocate a managed Exception instance and run its 
  constructor.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most likely, this 
  involves looking up resources for the various error messages.&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l3 level1 lfo7"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Probably take a trip through the OS kernel.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Often take a hardware 
  exception.&lt;/FONT&gt;&lt;/LI&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l3 level1 lfo7"&gt;&lt;FONT 
  face=Tahoma size=2&gt;Notify any attached debuggers, profilers, vectored 
  exception handlers and other interested parties.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
light years away from returning a -1 from your function call.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Exceptions are inherently non-local, and 
if there’s an obvious and enduring trend for today’s architectures, it’s that 
you must remain local for good performance.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Relative 
to straight-line local execution, exception performance will keep getting 
worse.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Sure, we might dig into our 
current behavior and speed it up a little.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But the trend will relentlessly make exceptions perform worse.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;How do I 
reconcile the trend to worse performance with our recommendation that managed 
code should use exceptions to communicate errors?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By ensuring that error cases are 
exceedingly rare.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We used to say 
that exceptions should be used for exceptional cases, but folks pushed back on 
that as tautological.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If your 
API fails in 10% of all calls, you better not use an exception.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, change the API so that it 
communicates its success or failure as part of the API (e.g. ‘bool 
TryParse(String s)’).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if the 
API fails 1% of calls, this may be too high a rate for a service that’s heavily 
used in a server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 1% of calls 
fail and we’re processing 1000 requests per second with 100 of these API calls 
per request, then we are throwing 1000 times a second.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s a &lt;I 
style="mso-bidi-font-style: normal"&gt;very&lt;/I&gt; disturbing rate of exceptions.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On the other hand, a 1% failure rate may 
be quite tolerable in a client scenario, if the exception occurs when a human 
user presses the wrong button.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Sometimes you won’t know whether your API will be used in a client or a 
server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it may be hard for you 
to predict failure rates when errors are triggered by bad data from the 
client.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you’ve provided a way 
for the client to check his data without triggering an exception (like the 
TryParse() example above) then you’ve done your part.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;As 
usual, there’s so much more to say.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;I still haven’t talked about unhandled exceptions.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or about undeniable exception 
propagation (Thread.Abort).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or how 
undeniable propagation interacts with propagation through unmanaged code via 
PInvoke, IJW or COM Interop.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I 
carefully avoided explaining why we didn’t follow our own rules when defining 
and using the Exception class hierarchy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And there’s plenty to say about our special treatment of 
OutOfMemoryException and StackOverflowException.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
are still reading and actually want to know more, perhaps you should just apply 
for a job on the CLR team.&lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51524" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item><item><title>Startup, Shutdown and related matters</title><link>http://blogs.msdn.com/b/cbrumme/archive/2003/08/20/51504.aspx</link><pubDate>Wed, 20 Aug 2003 18:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:51504</guid><dc:creator>cbrumme</dc:creator><slash:comments>45</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=51504</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2003/08/20/51504.aspx#comments</comments><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Usually 
I write blog articles on topics that people request via email or comments on 
other blogs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, nobody has ever 
asked me to write anything about shutdown.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But then 
I look at all the problems that occur during process shutdown in the unmanaged 
world.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These problems occur because 
many people don’t understand the rules, or they don’t follow the rules, or the 
rules couldn’t possibly work anyway.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We’ve 
taken a somewhat different approach for managed applications.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But I don’t think we’ve ever explained 
in detail what that approach is, or how we expect well-written applications to 
survive an orderly shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Furthermore, managed applications still execute within an unmanaged OS 
process, so they are still subject to the OS rules.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And in V1 and V1.1 of the CLR we’ve 
horribly violated some of those OS rules related to startup and shutdown.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’re trying to improve our behavior 
here, and I’ll discuss that too.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Questionable 
APIs&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Unfortunately, I can’t discuss the model for shutting down managed 
applications without first discussing how unmanaged applications terminate.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And, as usual, I’ll go off on a bunch of 
wild tangents.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Ultimately, every OS process shuts down via a call to ExitProcess or 
TerminateProcess.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;ExitProcess is 
the nice orderly shutdown, which notifies each DLL of the termination.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;TerminateProcess is ruder, in that the 
DLLs are not informed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
relationship between ExitProcess and TerminateProcess has a parallel in the 
thread routines ExitThread and TerminateThread.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;ExitThread is the nice orderly thread 
termination, whereas if you ever call TerminateThread you may as well kill the 
process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s almost guaranteed to 
be in a corrupt state.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, 
you may have terminated the thread while it holds the lock for the OS heap.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any thread attempting to allocate or 
release memory from that same heap will now block forever.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Realistically, Win32 shouldn’t contain a TerminateThread service.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To a first approximation, anyone who has 
ever used this service has injected a giant bug into his application.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it’s too late to remove it 
now.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In that 
sense, TerminateThread is like System.Threading.Thread.Suspend and Resume.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I cannot justify why I added those 
services.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OS SuspendThread and 
ResumeThread are extremely valuable to a tiny subset of applications.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CLR itself uses these routines to 
take control of threads for purposes like Garbage Collection and – as we’ll see 
later – for process shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As 
with TerminateThread, there’s a significant risk of leaving a thread suspended 
at a “bad” spot.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you call 
SuspendThread while a thread is inside the OS heap lock, you better not try to 
allocate or free from that same heap.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In a similar fashion, if you call SuspendThread while a thread holds the 
OS loader lock (e.g. while the thread is executing inside DllMain) then you 
better not call LoadLibrary, GetProcAddress, GetModuleHandle, or any of the other OS 
services that require that same lock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Even 
worse, if you call SuspendThread on a thread that is in the middle of exception 
dispatching inside the kernel, a subsequent GetThreadContext or SetThreadContext 
can actually produce a blend of the register state at the point of the 
suspension and the register state that was captured when the exception was 
triggered.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we attempt to modify 
a thread’s context (perhaps bashing the EIP – on X86 – to redirect the thread’s 
execution to somewhere it will synchronize with the GC or other managed 
suspension), our update to EIP might quietly get lost.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fortunately it’s possible to coordinate 
our user-mode exception dispatching with our suspension attempts in order to 
tolerate this race condition.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And 
probably the biggest gotcha with using the OS SuspendThread &amp;amp; ResumeThread 
services is on Win9X.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a Win9X 
box contains real-mode device drivers (and yes, some of them still do), then 
it’s possible for the hardware interrupt associated with the device to interact 
poorly with the thread suspension.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Calls to GetThreadContext can deliver a register state that is perturbed 
by the real-mode exception processing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The CLR installs a VxD on those operating systems to detect this case and 
retry the suspension.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
with sufficient care and discipline it’s possible to use the OS SuspendThread 
&amp;amp; ResumeThread to achieve some wonderful things.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But the 
managed Thread.Suspend &amp;amp; Resume are harder to justify.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They differ from the unmanaged 
equivalents in that they only ever suspend a thread at a spot inside managed 
code that is “safe for a garbage collection.”&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, we can report all the GC 
references at that spot and we can unwind the stack and register state to reveal 
our caller’s execution state.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Because 
we are at a place that’s safe for garbage collection, we can be sure that 
Thread.Suspend won’t leave a thread suspended while it holds an OS heap 
lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it may be suspended while 
it holds a managed Monitor (‘lock’ in C# or ‘SyncLock’ in VB.NET).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it may be suspended while it is 
executing the class constructor (.cctor) of an important class like 
System.String.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And over time we 
intend to write more of the CLR in managed code, so we can enjoy all the 
benefits.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When that happens, a 
thread might be suspended while loading a class or resolving security policy for 
a shared assembly or generating shared VTables for COM Interop.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The real 
problem is that developers sometimes confuse Thread.Suspend with a 
synchronization primitive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is 
not.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you want to synchronize two 
threads, you should use appropriate primitives like Monitor.Enter, 
Monitor.Wait, or WaitHandle.WaitOne.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Of course, it’s harder to use these primitives because you actually have 
to write code that’s executed by both threads so that they cooperate 
nicely.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And you have to eliminate 
the race conditions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I’m 
already wandering miles away from Shutdown, and I need to get back.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But I can’t resist first mentioning that 
TerminateThread is distinctly different from the managed Thread.Abort service, 
both in terms of our aspirations and in terms of our current 
implementation.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Nobody 
should ever call TerminateThread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Ever.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Today 
you can safely call Thread.Abort in two scenarios.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l8 level1 lfo4; tab-stops: list .5in" 
 &gt;&lt;FONT 
  face=Tahoma size=2&gt;You can call Abort on your own thread 
  (Thread.CurrentThread.Abort()).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;This is not much different than throwing any exception on your thread, 
  other than the undeniable manner in which the exception propagates.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The propagation is undeniable in the 
  sense that your thread will continue to abort, even if you attempt to swallow 
  the ThreadAbortException in a catch clause.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At the end-catch, the CLR notices that 
  an abort is in progress and we re-throw the abort.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You must either explicitly call the 
  ResetAbort method – which carries a security demand – or the exception must 
  propagate completely out of all managed handlers, at which point we reset the 
  undeniable nature of the abort and allow unmanaged code to (hopefully) swallow 
  it.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=2&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l8 level1 lfo4; tab-stops: list .5in" 
 &gt;&lt;FONT 
  face=Tahoma size=2&gt;An Abort is performed on all threads that have stack in an 
  AppDomain that is being unloaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Since we are throwing away the AppDomain anyway, we can often tolerate 
  surprising execution of threads at fairly arbitrary spots in their 
  execution.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if this leaves 
  managed locks unreleased and AppDomain statics in an inconsistent state, we’re 
  throwing away all that state as part of the unload anyway.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This situation isn’t as robust as we 
  would like it to be.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we’re 
  investing a lot of effort into improving our behavior as part of getting 
  “squeaky clean” for highly available execution inside SQL Server in our next 
  release.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Longer 
term, we’re committed to building enough reliability infrastructure around 
Thread.Abort that you can reasonably expect to use it to control threads that 
remain completely inside managed code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Aborting threads that interleave managed and unmanaged execution in a 
rich way will always remain problematic, because we are limited in how much we 
can control the unmanaged portion of that execution.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;ExitProcess 
in a nutshell&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So what 
does the OS ExitProcess service actually do?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ve never read the source code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But based on many hours of stress 
investigations, it seems to do the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Kill all the threads except one, 
whatever they are doing in user mode.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;On NT-based operating systems, the surviving thread is the thread that 
called ExitProcess.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This becomes 
the shutdown thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On Win9X-based 
operating systems, the surviving thread is somewhat random.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I suspect that it’s the last thread to 
get around to committing suicide.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Once only one thread survives, no 
further threads can enter the process… almost.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On NT-based systems, I only see 
superfluous threads during shutdown if a debugger attaches to the process during 
this window.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On Win9X-based 
systems, any threads that were created during this early phase of shutdown are 
permitted to start up.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
DLL_THREAD_ATTACH notifications to DllMain for the starting threads will be 
arbitrarily interspersed with the DLL_PROCESS_DETACH notifications to DllMain 
for the ensuing shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As you 
might expect, this can cause crashes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;3)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Since only one thread has survived 
(on the more robust NT-based operating systems), the OS now weakens all the 
CRITICAL_SECTIONs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is mixed 
blessing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It means that the 
shutdown thread can allocate and free objects from the system heap without 
deadlocking.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it means that 
application data structures protected by application CRITICAL_SECTIONs are 
accessible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it also means that 
the shutdown thread can see corrupt application state.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If one thread was wacked in step #1 
above while it held a CRITICAL_SECTION and left shared data in an inconsistent 
state, the shutdown thread will see this inconsistency and must somehow tolerate 
it. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Also, data structures that are 
protected by synchronization primitives other than CRITICAL_SECTION are still 
prone to deadlock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;4)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The OS calls the DllMain of each 
loaded DLL, giving it a DLL_PROCESS_DETACH notification.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The ‘lpReserved’ argument to DllMain 
indicates whether the DLL is being unloaded from a running process or whether 
the DLL is being unloaded as part of a process shutdown.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(In the case of the CLR’s DllMain, we 
only ever receive the latter style of notification.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once we’re loaded into a process, we 
won’t be unloaded until the process goes away).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN 
style="mso-list: Ignore"&gt;&lt;FONT face=Tahoma size=2&gt;5)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The process actually terminates, 
and the OS reclaims all the resources associated with the process.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Well, 
that sounds orderly enough.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But try 
running a multi-threaded process that calls ExitProcess from one thread and 
calling HeapAlloc / HeapFree in a loop from a second thread.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you have a debugger attached, 
eventually you will trap with an ‘INT 3’ instruction in the OS heap code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OutputDebugString message will 
indicate that a block has been freed, but has not been added to the free list… 
It has been leaked.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because 
the ExitProcess wacked your 2&lt;SUP&gt;nd&lt;/SUP&gt; thread while it was in the middle of 
a HeapFree operation.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
symptomatic of a larger problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 
you wack threads while they are performing arbitrary processing, your 
application will be left in an arbitrary state.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the DLL_PROCESS_DETACH 
notifications reach your DllMain, you must tolerate that arbitrary 
state.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I’ve 
been told by several OS developers that it is the application’s responsibility 
to take control of all the threads before calling ExitProcess.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That way, the application will be in a 
consistent state when DLL_PROCESS_DETACH notifications occur. If you work in the 
operating system, it’s reasonable to consider the “application” to be a 
monolithic homogenous piece of code written by a single author.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So of course that author should put his 
house in order and know what all the threads are doing before calling 
ExitProcess.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;But if 
you work on an application, you know that there are always multiple components 
written by multiple authors from different vendors.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These components are only loosely aware 
of each other’s implementations – which is how it should be.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And some of these components have extra 
threads on the side, or they are performing background processing via 
IOCompletion ports, threadpools, or other techniques.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Under 
those conditions, nobody can have the global knowledge and global control 
necessary to call ExitProcess “safely”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;So, regardless of the official rules, ExitProcess will be called while 
various threads are performing arbitrary processing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;The OS 
Loader Lock&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;It’s 
impossible to discuss the Win32 model for shutting down a process without 
considering the OS loader lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This is a lock that is present on all Windows operating systems.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It provides mutual exclusion during 
loading and unloading.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Unfortunately, this lock is held while application code executes.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This fact alone is sufficient to 
guarantee disaster.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
can avoid it, you must never hold one of your own locks while calling into 
someone else’s code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They will 
screw you every time.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Like all 
good rules, this one is made to be broken.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The CLR violates this rule in a few places.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, we hold a ‘class 
constructor’ lock for your class when we call your .cctor method.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, the CLR recognizes that this 
fact can lead to deadlocks and other problems.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we have rules for weakening this lock 
when we discover cycles of .cctor locks in the application, even if these cycles 
are distributed over multiple threads in multi-threaded scenarios.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we can see through various other 
locks, like the locks that coordinate JITting, so that larger cycles can be 
detected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, we deliberately 
don’t look through user locks (though we could see through many of these, like 
Monitors, if we chose).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once we 
discover a visible, breakable lock, we allow one thread in the cycle to see 
uninitialized state of one of the classes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This allows forward progress and the application continues.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;See my earlier blog on “Initializing 
code” for more details.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Incidentally, I find it disturbing that there’s often little discipline 
in how managed locks like Monitors are used.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These locks are so convenient, 
particularly when exposed with language constructs like C# lock and VB.NET 
SyncLock (which handle backing out of the lock during exceptions), that many 
developers ignore good hygiene when using them.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if code uses multiple locks 
then these locks should typically be ranked so that they are always acquired in 
a predictable order.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is one 
common technique for avoiding deadlocks.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
back to the loader lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt; The 
OS takes this lock implicitly when it is executing inside APIs like 
GetProcAddress, GetModuleHandle and GetModuleFileName.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By holding this lock inside these APIs, 
the OS ensures that DLLs are not loading and unloading while it is groveling 
through whatever tables it uses to record the state of the process.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So if 
you call those APIs, you are implicitly acquiring a lock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;That 
same lock is also acquired during a LoadLibrary, FreeLibrary, or CreateThread 
call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And – while it is held – the 
operating system will call your DllMain routine with a notification.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The notifications you might see 
are:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;FONT size=2&gt;&lt;FONT 
face=Tahoma&gt;DLL_THREAD_ATTACH&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
thread that calls your DllMain has just been injected into the process.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you need to eagerly allocate any TLS 
state, this is your opportunity to do so.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In the managed world, it is preferable to allocate TLS state lazily on 
the first TLS access on a given thread.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;FONT size=2&gt;&lt;FONT 
face=Tahoma&gt;DLL_THREAD_DETACH&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
thread that calls your DllMain has finished executing the thread procedure that 
it was started up with.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After it 
finishes notifying all the DLLs of its death in this manner, it will 
terminate.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Many unmanaged 
applications use this notification to de-allocate their TLS data.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the managed world, managed TLS is 
automatically cleaned up without your intervention.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This happens as a natural consequence of 
garbage collection.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;FONT size=2&gt;&lt;FONT 
face=Tahoma&gt;DLL_PROCESS_ATTACH&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
thread that calls your DllMain is loading your DLL via an explicit LoadLibraryEx 
call or similar technique, like a static bind.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The lpReserved argument indicates 
whether a dynamic or static bind is in progress.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is your opportunity to initialize 
any global state that could not be burned into the image.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, C++ static initializers 
execute at this time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The managed 
equivalent has traditionally been a class constructor method, which executes 
once per AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a future 
version of the CLR, we hope to provde a more convenient module constructor 
concept.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;FONT size=2&gt;&lt;FONT 
face=Tahoma&gt;DLL_PROCESS_DETACH&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If the 
process is terminating in an orderly fashion (ExitProcess), your DllMain will 
receive a DLL_PROCESS_DETACH notification where the lpReserved argument is 
non-null.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the process is 
terminating in a rude fashion (TerminateProcess), your DllMain will receive no 
notification.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If someone unloads 
your DLL via a call to FreeLibrary or equivalent, the process will continue 
executing after you unload.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This case is indicated by a null value for 
lpReserved.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the managed world, de-initialization 
happens through notifications of AppDomain unload or process exit, or through 
finalization activity.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;The DLL_THREAD_ATTACH and 
DLL_THREAD_DETACH calls have a performance implication.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you have loaded 
100 DLLs into your process and you start a new thread, that thread must call 100 
different DllMain routines.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s say that these routines touch a page or 
two of code each, and a page of data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That might be 250 pages (1 MB) in your 
working set, for no good reason.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;The CLR calls DisableThreadLibraryCalls 
on all managed assemblies other than certain MC++ IJW assemblies (more on this 
later) to avoid this overhead for you.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it’s a good idea to do the same on your 
unmanaged DLLs if they don’t need these notifications to manage their 
TLS.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Writing code inside DllMain is one of 
the most dangerous places to write code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is because you are executing inside a 
callback from the OS loader, inside the OS loader lock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Here are some of the rules related to 
code inside DllMain:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l10 level1 lfo2; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;You must never call LoadLibrary or 
otherwise perform a dynamic bind.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l10 level1 lfo2; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;You must never attempt to acquire a 
lock, if that lock might be held by a thread that needs the OS loader lock.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Acquiring a heap 
lock by calling HeapAlloc or HeapFree is probably okay).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l10 level1 lfo2; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;3)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;You should never call into another 
DLL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
danger is that the other DLL may not have initialized yet, or it may have 
already uninitialized.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Calling into kernel32.dll is probably 
okay).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l10 level1 lfo2; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;4)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;You should never start up a thread or 
terminate a thread, and then rendezvous with that other thread’s start or 
termination.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;As we shall see, the CLR violates some 
of these rules.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And these violations have resulted in serious consequences for managed 
applications – particularly managed applications written in MC++.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;And if you’ve ever written code inside 
DllMain – including code that’s implicitly inside DllMain like C++ static 
initializers or ‘atexit’ routines – then you’ve probably violated some of these 
rules.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rule #3 
is especially harsh.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;The fact is, programs violate these 
rules all the time and get away with it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Knowing this, the MC++ and CLR teams made a 
bet that they could violate some of these rules when executing IJW 
assemblies.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It 
turns out that we bet wrong.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I’m going to explain exactly how we 
screwed this up with IJW assemblies, but first I need to explain what IJW 
assemblies are.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;IJW&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;IJW is how we internally refer to mixed 
managed / unmanaged images.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you compile a MC++ assembly with ‘/clr’ in 
V1 or V1.1, it almost certainly contains a mixture of managed and unmanaged 
constructs.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;In future versions, I expect there will 
be ways to compile MC++ assemblies with compiler-enforced guarantees that the 
image is guaranteed pure managed, or guaranteed pure verifiable managed, or – 
ultimately – perhaps even pure verifiable 32-bit / 64-bit neutral managed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In each case, the 
compiler will necessarily have to restrict you to smaller and smaller subsets of 
the C++ language.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;For example, verifiable C++ cannot use arbitrary unmanaged pointers.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, it must 
restrict itself to managed pointers and references, which are reported to the 
garbage collector and which follow certain strict rules.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Furthermore, 32-bit 
/ 64-bit neutral code cannot consume the declarations strewn through the 
windows.h headers, because these pick a word size during compilation.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;IJW is an acronym for “It Just Works” 
and it reflects the shared goal of the C++ and CLR teams to transparently 
compile existing arbitrary C++ programs into IL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I think we did an amazing job of approaching 
that goal, but of course not everything “just works.”&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, there are a 
number of constructs like inline assembly language that cannot be converted to 
managed execution.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The C++ compiler, linker and CLR ensure that these methods are left as 
unmanaged and that managed callers transparently switch back to unmanaged before 
calling them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;So inline X86 assembly language must 
necessarily remain in unmanaged code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some other constructs are currently left in 
unmanaged code, though with sufficient effort we could provide managed 
equivalents.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;These other constructs include setjmp / longjmp, member pointers (like 
pointer to virtual method), and a reasonable startup / shutdown story (which is 
what this blog article is &lt;I style="mso-bidi-font-style: normal"&gt;supposed&lt;/I&gt; to be about).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I’m not sure if we ever documented the 
constructs that are legal in a pure managed assembly, vs. those constructs which 
indicate that the assembly is IJW.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Certainly we have a strict definition of this 
distinction embedded in our code, because the managed loader considers it when 
loading.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some 
of the things we consider are:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo3; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;A pure 
  managed assembly has exactly one DLL import.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;This import is to mscoree.dll’s _CorExeMain 
  (for an EXE) or _CorDllMain (for a DLL).&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;The entrypoint of the EXE or DLL must be a 
  JMP to this import.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;This is how we force the runtime to load and get control whenever a 
  managed assembly is loaded.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo3; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;A pure 
  managed assembly can have no DLL exports.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;When we bind to pure managed assemblies, it 
  is always through managed Fusion services, via AssemblyRefs and assembly 
  identities (ideally with cryptographic strong names).&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo3; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;A pure 
  managed assembly has exactly one rebasing fixup.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This fixup is for 
  the JMP through the import table that I mentioned above.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unmanaged EXEs 
  tend to strip all their rebasing fixups, since EXEs are almost guaranteed to 
  load at their preferred addresses.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;However, managed EXEs can be loaded like 
  DLLs into a running process.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;That single fixup is useful for cases where 
  we want to load via LoadLibraryEx on versions of the operating system that 
  support this.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo3; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;A pure 
  managed assembly has no TLS section and no other exotic constructs that are 
  legal in arbitrary unmanaged PE files.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Of course, IJW assemblies can have many 
imports, exports, fixups, and other constructs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As with pure managed assemblies, the 
entrypoint is constrained to be a JMP to mscoree.dll’s _CorExeMain or 
_CorDllMain function.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This is the “outer entrypoint”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, the COM+ header of the PE file has 
an optional “inner entrypoint”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once the CLR has proceeded far enough into 
the loading process on a DLL, it will dispatch to this inner entrypoint which 
is… your normal DllMain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In V1 and V1.1, this inner entrypoint is 
expressed as a token to a managed function.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if your DllMain is written as an 
unmanaged function, we dispatch to a managed function which is defined as a 
PInvoke out to the unmanaged function.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Now we can look at the set of rules for 
what you can do in a DllMain, and compare it to what the CLR does when it sees 
an IJW assembly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The results aren’t pretty.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Remember that inside DllMain:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;U&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;You must never call LoadLibrary or otherwise perform a 
dynamic bind&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/U&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;With normal managed assemblies, this 
isn’t a concern.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;For example, most pure managed assemblies are loaded through 
Assembly.Load or resolution of an AssemblyRef – outside of the OS loader 
lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even 
activation of a managed COM object through OLE32’s CoCreateInstance will 
sidestep this issue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The registry entries for the CLSID always mention mscoree.dll as the 
server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A 
subkey is consulted by mscoree.dll – inside DllGetClassObject and outside of the 
OS loader lock – to determine which version of the runtime to spin up and which 
assembly to load.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;But IJW assemblies have arbitrary DLL 
exports.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Therefore other DLLs, whether unmanaged or themselves IJW, can have 
static or dynamic (GetProcAddress) dependencies on an IJW assembly.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the OS loads 
the IJW assembly inside the loader lock, the OS further resolves the static 
dependency from the IJW assembly to mscoree.dll’s _CorDllMain.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Inside _CorDllMain, 
we must select an appropriate version of the CLR to initialize in the 
process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This 
involves calling LoadLibrary on a particular version of mscorwks.dll, violating 
our first rule for DllMain.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;So what goes wrong when this rule is 
violated?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Well, the OS loader has already processed all the DLLs and their imports, 
walking the tree of static dependencies and forming a loading plan.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is now executing 
on this plan.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Let’s say that the loader’s plan is to first initialize an IJW assembly, 
then initialize its dependent mscoree.dll reference, and then initialize 
advapi32.dll.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;(By ‘initialize’, I mean give that DLL its DLL_PROCESS_ATTACH 
notification).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;When mscoree.dll decides to LoadLibrary mscorwks.dll, a new loader plan 
must be created.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;If mscorwks.dll depends on advapi32.dll (and of course it does), we have 
a problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
OS loader already has advapi32.dll on its pending list.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It will initialize 
that DLL when it gets far enough into its original loading plan, but not 
before.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;If mscorwks.dll needs to call some APIs 
inside advapi32.dll, it will now be making those calls before advapi32.dll’s 
DllMain has been called.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This can and does lead to arbitrary 
failures.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I 
personally hear about problems with this every 6 months or so.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s a pretty low 
rate of failure.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But one of those failures was triggered when a healthy application 
running on V1 of the CLR was moved to V1.1 of the CLR.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ouch.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;U&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;You must never attempt to acquire a lock, if that lock 
might be held by a thread that needs the OS loader lock&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/U&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;It’s not possible to execute managed 
code without potentially acquiring locks on your thread.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, we may 
need to initialize a class that you need access to.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that class isn’t 
already initialized in your AppDomain, we will use a .cctor lock to coordinate 
initialization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Along the same lines, if a method requires JIT compilation we will use a 
lock to coordinate this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if your thread allocates a managed 
object, it may have to take a lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(We don’t take a lock on each allocation if 
we are executing on a multi-processor machine, for obvious reasons.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But eventually your 
thread must coordinate with the garbage collector via a lock before it can 
proceed with more allocations).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;So if you execute managed code inside 
the OS loader lock, you are going to contend for a CLR lock.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now consider what 
happens if the CLR ever calls GetModuleHandle or GetProcAddress or 
GetModuleFileName while it holds one of those other locks.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This includes 
implicit calls to LoadLibrary / GetProcAddress as we fault in any lazy DLL 
imports from the CLR.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Unfortunately, the sequence of lock 
acquisition is inverted on the two threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This yields a classic deadlock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Once again, this isn’t a concern for 
pure managed assemblies.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The only way a pure managed assembly can 
execute managed code inside the OS loader lock is if some unmanaged code 
explicitly calls into it via a marshaled out delegate or via a COM call from &lt;I 
style="mso-bidi-font-style: normal"&gt;its own&lt;/I&gt; 
DllMain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;That’s a bug in the unmanaged code!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But with an IJW assembly, some methods are 
managed and some are unmanaged.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The compiler, linker and CLR conspire to make 
this fact as transparent as possible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But any call from your DllMain (i.e. from 
your inner entrypoint) to a method that happened to be emitted as IL will set 
you up for this deadlock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;U&gt;&lt;FONT face=Tahoma size=2&gt;You should 
never call into another DLL&lt;/FONT&gt;&lt;/U&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;It’s really not possible to execute 
managed code without making cross-DLL calls.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The JIT compiler is in a different DLL from 
the ExecutionEngine.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The ExecutionEngine is in a different DLL from your IJW 
assembly.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Once again, pure managed assemblies 
don’t usually have a problem here.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I did run into one case where one of the 
Microsoft language compilers was doing a LoadLibrary of mscorlib.dll.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This had the side 
effect of spinning up the CLR inside the OS loader lock and inflicting all the 
usual IJW problems onto the compilation process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since managed assemblies have no DLL exports, 
it’s rare for applications to load them in this manner.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of this 
language compiler, it was doing so for the obscure purpose of printing a banner 
to the console at the start of compilation, telling the user what version of the 
CLR it was bound to.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;There are much better ways of doing this sort of thing, and none of those 
other ways would interfere with the loader lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This has been corrected.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;U&gt;You should never start up a thread or terminate a thread, 
and then rendezvous&lt;/U&gt;&lt;/I&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;This probably doesn’t sound like 
something you would do.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And yet it’s one of the most common deadlocks 
I see with IJW assemblies on V1 and V1.1 of the CLR.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The typical stack 
trace contains a load of an IJW assembly, usually via a DLL import.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This causes 
mscoree.dll’s _CorDllMain to get control.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Eventually, we notice that the IJW assembly 
has been strong name signed, so we call into WinVerifyTrust in 
WinTrust.dll.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;That API has a perfectly reasonable expectation that it is not inside the 
OS loader lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;It calls into the OS threadpool (not the managed CLR threadpool), which 
causes the OS threadpool to lazily initialize itself.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Lazy initialization 
involves spinning up a waiter thread, and then blocking until that waiter thread 
starts executing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Of course, the new waiter thread must 
first deliver DLL_THREAD_ATTACH notifications to any DLLs that expect such 
notifications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And it must obviously obtain the OS loader lock before it can deliver the 
first notification.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The result is a deadlock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;So I’ve painted a pretty bleak picture 
of all the things that can go wrong with IJW assemblies in V1 and V1.1 of the 
CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we had 
seen a disturbing rate of failures prior to shipping V1, we would have 
reconsidered our position here.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it wasn’t until later that we had enough 
external customers running into these difficulties.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With the benefits 
of perfect hindsight, it is now clear that we screwed up.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Fortunately, much of this is fixable in 
our next release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Until then, there are some painful workarounds that might bring you some 
relief.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s 
look at the ultimate solution first, and then you can see how the workarounds 
compare.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We 
think that the ultimate solution would consist of several parts:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l6 level1 lfo6; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Just 
  loading an IJW assembly must not spin up a version of the CLR.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because 
  spinning up a version of the CLR necessarily involves a dynamic load, and 
  we’ve seen that dynamic loads are illegal during loading and initializing of 
  static DLL dependencies.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Instead, mscoree.dll must perform enough 
  initialization of the IJW assembly without actually setting up a full 
  runtime.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;This means that all calls into the managed portion of the IJW assembly 
  must be bashed so that they lazily load a CLR and initialize it on first 
  call.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=2&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l6 level1 lfo6; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Along the 
  same lines, the inner entrypoint of an IJW assembly must either be omitted or 
  must be encoded as an unmanaged entrypoint.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Recall that the current file format doesn’t 
  have a way of representing unmanaged inner entrypoints, since this is always 
  in the form of a token.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Even if the token refers to an unmanaged 
  method, we would have to spin up a version of the CLR to interpret that token 
  for us.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So 
  we’re going to need a tweak to the current file format to enable unmanaged 
  inner entrypoints.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=3&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l6 level1 lfo6; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;An 
  unmanaged inner entrypoint is still a major risk.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that inner 
  entrypoint calls into managed code, we will trap the call and lazily spin up 
  the correction version of the CLR.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;At that point, you are in exactly the same 
  situation as if we had left the entrypoint as managed.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ideally, 
  assembly-level initialization and uninitialization would never happen inside 
  the OS loader lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Instead, they would be replaced with modern managed analogs that are 
  unrelated to the unmanaged OS loader’s legacy behavior.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you read my 
  old blog on “Initializing code” at &lt;/FONT&gt;&lt;A 
  href="http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/611cdfb1-2865-4957-9a9c-6e2655879323" 
  &gt;&lt;FONT face=Tahoma size=2 
  &gt;http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/611cdfb1-2865-4957-9a9c-6e2655879323&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
  face=Tahoma size=2&gt;, I mention that we’re under some 
  pressure to add a module-level equivalent of .cctor methods.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That mechanism 
  would make a great replacement for traditional DLL_PROCESS_ATTACH 
  notifications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;In fact, the CLR has always supported a .cctor method at a global 
  module scope.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;However, the semantics associated with such a method was that it ran 
  before any access to static members at global module scope.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A more useful 
  semantic for a future version of the CLR would be for such a global .cctor to 
  execute before any access to members in the containing Module, whether global 
  or contained in any of the Module’s types.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=4&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l6 level1 lfo6; tab-stops: list .5in" 
  &gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma 
  &gt;The above changes make it possible to avoid execution of 
  managed code inside the OS loader lock.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;But it’s still possible for a naïve or 
  misbehaved unmanaged application to call a managed service (like a marshaled 
  out delegate or a managed COM object) from inside DllMain.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This final 
  scenario is not specific to IJW.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;All managed execution is at risk to this 
  kind of abuse.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Ideally, the CLR would be able to detect attempts to enter it while the 
  loader lock is held, and fail these attempts.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;It’s not clear whether such detection / 
  prevention should be unconditional or whether it should be enabled through a 
  Customer Debug Probe.&lt;I style="mso-bidi-font-style: normal" 
  &gt;&lt;o:p&gt;&lt;/O:P&gt;&lt;/I&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;FONT face=Tahoma 
size=2&gt;If you don’t know what Customer Debug Probes are, 
please hunt them down on MSDN.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They are a life-saver for debugging certain 
difficult problems in managed applications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I would recommend starting with &lt;/FONT&gt;&lt;A 
href="http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=c7b955c7-231a-406c-9fa5-ad09ef3bb37f"&gt;&lt;FONT face=Tahoma size=2&gt;http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=c7b955c7-231a-406c-9fa5-ad09ef3bb37f&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;, and then reading most of Adam Nathan’s 
excellent blogs at &lt;/FONT&gt;&lt;A href="http://blogs.gotdotnet.com/anathan"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.gotdotnet.com/anathan&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;.&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;I 
style="mso-bidi-font-style: normal"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Of the above 4 changes, we’re relatively 
confident that the first 3 will happen in the next release.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We also 
experimented with the 4&lt;SUP&gt;th&lt;/SUP&gt; change, but it’s 
unlikely that we will make much further progress.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A key obstacle is that there is no 
OS-approved way that can efficiently detect execution inside the loader 
lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Our hope 
is that a future version of the OS would provide such a mechanism.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;This is all great.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But you have an 
application that must run on V1 or V1.1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What options do you have?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fortunately, Scott 
Currie has written an excellent article on this very subject.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you build IJW 
assemblies, please read it at &lt;/FONT&gt;&lt;A 
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconmixeddllloadingproblem.asp"&gt;&lt;FONT face=Tahoma size=2&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconmixeddllloadingproblem.asp&lt;/FONT&gt;&lt;/A&gt;&lt;FONT 
face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;The Pure Managed 
Story&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;If you code in a language other than 
MC++, you’re saying “Enough about IJW and the OS loader lock 
already.”&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Let’s look at what the CLR does during 
process shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;I’ll try not to mention IJW, but I’ll have to keep talking about that 
darn loader lock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;From the point of view of a managed 
application, there are three types of shutdown:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo7; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;A shutdown initiated by a call to 
TerminateProcess doesn’t involve any further execution of the CLR or managed 
code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;From our 
perspective, the process simply disappears.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the rudest of all shutdowns, and 
neither the CLR developer nor the managed developer has any obligations related 
to it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo7; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;A shutdown initiated by a direct call to 
ExitProcess is an unorderly shutdown from the point of view of the managed 
application.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Our first notification of the shutdown is via a DLL_PROCESS_DETACH 
notification.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This notification could first be delivered to the DllMain of 
mscorwks.dll, mscoree.dll, or any of the managed assemblies that are currently 
loaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Regardless of which module gets the notification first, it is always 
delivered inside the OS loader lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is not safe to execute any managed code at 
this time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So 
the CLR performs a few house-keeping activities and then returns from its 
DllMain as quickly as possible.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since no managed code runs, the managed 
developer still has no obligations for this type of shutdown.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo7; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;3)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;An orderly managed shutdown gives 
managed code an opportunity to execute outside of the OS loader lock, prior to 
calling ExitProcess.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;There are several ways we can encounter an orderly shutdown.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Because we will 
execute managed code, including Finalize methods, the managed developer must 
consider this case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Examples of an orderly managed shutdown 
include:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo8; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;Call System.Environment.Exit().&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I already mentioned 
that some Windows developers have noted that you must not call ExitProcess 
unless you first coordinate all your threads… and then they work like mad to 
make the uncoordinated case work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For Environment.Exit we are under no 
illusions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We 
expect you to call it in races from multiple threads at arbitrary times.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s our job to 
somehow make this work.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo8; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;If a process is launched with a managed 
EXE, then the CLR tracks the number of foreground vs. background managed 
threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(See 
Thread.IsBackground).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;When the number of foreground threads drops to zero, the CLR performs an 
orderly shutdown of the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that the distinction between foreground 
and background threads serves exactly this purpose and no other 
purpose.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo8; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;3)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;Starting with MSVCRT 7.0, an explicit 
call to ‘exit()’ or an implicit call to ‘exit()’ due to a return from ‘main()’ 
can turn into an orderly managed shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The CRT checks to see if mscorwks.dll or 
mscoree.dll is in the process (I forget which).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If it is resident, then it calls 
CorExitProcess to perform an orderly shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Prior to 7.0, the CRT is of course unaware of 
the CLR.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo8; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;4)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;Some unmanaged applications are aware of 
the CLR’s requirements for an orderly shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;An example is devenv.exe, which is the EXE 
for Microsoft Visual Studio.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Starting with version 7, devenv calls 
CoEEShutDownCOM to force all the CLR’s references on COM objects to be 
Release()’d.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;This at least handles part of the managed shutdown in an orderly 
fashion.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s 
been a while since I’ve looked at that code, but I think that ultimately devenv 
triggers an orderly managed shutdown through a 2&lt;SUP&gt;nd&lt;/SUP&gt; API.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;If you are following along with the 
Rotor sources, this all leads to an interesting quirk of EEShutDown in 
ceemain.cpp.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;That method can be called:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l7 level1 lfo9; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;0 times, if 
  someone calls TerminateProcess.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l7 level1 lfo9; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;1 time, if 
  someone initiates an unorderly shutdown via ExitProcess.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l7 level1 lfo9; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;2 times, if 
  we have a single-threaded orderly shutdown.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;In this case, the first call is made 
  outside of the OS loader lock.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Later, we call ExitProcess for the 2&lt;SUP 
  &gt;nd&lt;/SUP&gt; half of the shutdown.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This causes 
  EEShutDown to be called a 2&lt;SUP&gt;nd&lt;/SUP&gt; time.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l7 level1 lfo9; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Even more 
  times, if we have a multi-threaded orderly shutdown.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Many threads will 
  race to call EEShutDown the first time, outside the OS loader lock.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This routine 
  protects itself by anointing a winner to proceed with the shutdown.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then the eventual 
  call to ExitProcess causes the OS to kill all threads except one, which calls 
  back to EEShutDown inside the OS loader lock.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Of course, our passage through 
EEShutDown is quite different when we are outside the OS loader lock, compared 
to when we are inside it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we are outside, we do something like 
this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo10; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;First we 
  synchronize at the top of EEShutDown, to handle the case where multiple 
  threads race via calls to Environment.Exit or some equivalent 
  entrypoint.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo10; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Then we 
  finalize all objects that are unreachable.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;This finalization sweep is absolutely 
  normal and occurs while the rest of the application is still running.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo10; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Then we 
  signal for the finalizer thread to finish its normal activity and participate 
  in the shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;The first thing it does is raise the AppDomain.ProcessExit event.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once we get past 
  this point, the system is no longer behaving normally.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You could either 
  listen to this event, or you could poll System.Environment.HasShutdownStarted 
  to discover this fact.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;This can be an important fact to discover 
  in your Finalize method, because it’s more difficult to write robust 
  finalization code when we have started finalizing &lt;I 
  style="mso-bidi-font-style: normal"&gt;reachable&lt;/I&gt; 
  objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;It’s no longer possible to depend on WaitHandles like Events, remoting 
  infrastructure, or other objects.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;The other time we can finalize reachable 
  objects is during an AppDomain unload.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;This case can be discovered by listening to 
  the AppDomain.DomainUnload event or by polling for the 
  AppDomain.IsFinalizingForUnload state.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;The other nasty thing to keep in mind is 
  that you can only successfully listen to the ProcessExit event from the 
  Default AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;This is something of a bug and I think we would like to try fixing it 
  for the next release.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo10; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Before we 
  can start finalizing reachable objects, we suspend all managed activity.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a 
  suspension from which we will never resume.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Our goal is to minimize the number of 
  threads that are surprised by the finalization of reachable state, like static 
  fields, and it’s similar to how we prevent entry to a doomed AppDomain when we 
  are unloading it.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo10; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;This 
  suspension is unusual in that we allow the finalizer thread to bypass the 
  suspension.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Also, we change suspended threads that are in STAs, so that they pump 
  COM messages.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;We would never do this during a garbage collection, since the 
  reentrancy would be catastrophic.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;(Threads are suspended for a GC at pretty 
  arbitrary places… down to an arbitrary machine code instruction boundary in 
  many typical scenarios).&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;But since we are never going to resume from 
  this suspension, and since we don’t want cross-apartment COM activity to 
  deadlock the shutdown attempt, pumping makes sense here.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This suspension 
  is also unusual in how we raise the barrier against managed execution.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For normal GC 
  suspensions, threads attempting to call from unmanaged to managed code would 
  block until the GC completes.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;In the case of a shutdown, this could cause 
  deadlocks when it is combined with cross-thread causality (like synchronous 
  cross-apartment calls).&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Therefore the barrier behaves differently 
  during shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Returns into managed code block normally.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But calls into 
  managed code are failed.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;If the call-in attempt is on an HRESULT 
  plan, we return an HRESULT.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;If it is on an exception plan, we 
  throw.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
  exception code we raise is 0xC0020001 and the argument to RaiseException is a 
  failure HRESULT formed from the ERROR_PROCESS_ABORTED SCODE (0x1067).&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l3 level1 lfo10; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Once all 
  objects have been finalized, even if they are reachable, then we Release() all 
  the COM pUnks that we are holding.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Normally, releasing a chain of pUnks from a 
  traced environment like the CLR involves multiple garbage collections.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each collection 
  discovers a pUnk in the chain and subsequently Release’s it.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If that Release 
  on the unmanaged side is the final release, then the unmanaged pUnk will be 
  free’d.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 
  that pUnk contains references to managed objects, those references will now be 
  dropped.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A 
  subsequent GC may now collect this managed object and the cycle begins 
  again.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So a 
  chain of pUnks that interleaves managed and unmanaged execution can require a 
  GC for each interleaving before the entire chain is recovered.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;During shutdown, 
  we bypass all this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Just as we finalize objects that are reachable, we also drop all 
  references to unmanaged pUnks, even if they are reachable.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;From the perspective of managed code, at 
this point we are finished with the shutdown, though of course we perform many 
more steps for the unmanaged part of the shutdown.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;There are a couple of points to note 
with the above steps.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l4 level1 lfo11; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;We never 
  unwind threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Every so often developers express their surprise that ‘catch’, ‘fault’, 
  ‘filter’ and ‘finally’ clauses haven’t executed throughout all their threads 
  as part of a shutdown.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;But we would be nuts to try this.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s just too 
  disruptive to throw exceptions through threads to unwind them, unless we have 
  a compelling reason to do so (like AppDomain.Unload).&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if those 
  threads contain unmanaged execution on their threads, the likelihood of 
  success is even lower.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;If we were on that plan, some small 
  percentage of attempted shutdowns would end up with “Unhandled Exception / 
  Debugger Attach” dialogs, for no good reason.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=2&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l4 level1 lfo11; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;Along the 
  same lines, developers sometimes express their surprise that all the 
  AppDomains aren’t unloaded before the process exits.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once again, the 
  benefits don’t justify the risk or the overhead of taking these extra 
  steps.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 
  you have termination code you must run, the ProcessExit event and Finalizable 
  objects should be sufficient for doing so.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1 start=3&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l4 level1 lfo11; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;We run most 
  of the above shutdown under the protection of a watchdog thread.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By this I mean 
  that the shutdown thread signals the finalizer thread to perform most of the 
  above steps.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Then the shutdown thread enters a wait with a timeout.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the timeout 
  triggers before the finalizer thread has completed the next stage of the 
  managed shutdown, the shutdown thread wakes up and skips the rest of the 
  managed part of the shutdown.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;It does this by calling ExitProcess.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is almost 
  fool-proof.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Unfortunately, if the shutdown thread is an STA thread it will pump COM 
  messages (and SendMessages), while it is performing this watchdog blocking 
  operation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;If it picks up a COM call into its STA that deadlocks, then the process 
  will hang.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;In a future release, we can fix this by using an extra thread.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve hesitated 
  to do so in the past because the deadlock is exceedingly rare, and because 
  it’s so wasteful to burn a thread in this manner.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Finally, a lot more happens inside 
EEShutDown than the orderly managed steps listed above.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have some 
unmanaged shutdown that doesn’t directly impact managed execution.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even here we try 
hard to limit how much we do, particularly if we’re inside the OS loader 
lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we 
must shutdown inside the OS loader lock, we mostly just flush any logs we are 
writing and detach from trusted services like the profiler or 
debugger.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;One thing we do &lt;I 
style="mso-bidi-font-style: normal"&gt;not&lt;/I&gt; do during 
shutdown is any form of leak detection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is somewhat controversial.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are a number 
of project teams at Microsoft which require a clean leak detection run whenever 
they shutdown.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And that sort of approach to leak detection has been formalized in 
services like MSVCRT’s _CrtDumpMemoryLeaks, for external use.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The basic idea is 
that if you can find what you have allocated and release it, then you never 
really leaked it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Conversely, if you cannot release it by the time you return from your 
DllMain then it’s a leak.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I’m not a big fan of that approach to 
finding memory leaks, for a number of reasons:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l11 level1 lfo12; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;The fact 
  that you can reclaim memory doesn’t mean that you were productively using 
  it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For 
  example, the CLR makes extensive use of “loader heaps” that grow without 
  release until an AppDomain unloads.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;At that point, we discard the entire heap 
  without regard for the fine-grained allocations within it.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The fact that we 
  remembered where all the heaps are doesn’t really say anything about whether 
  we leaked individual allocations within those heaps.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l11 level1 lfo12; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;In a few 
  well-bounded cases, we intentionally leak.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;For example, we often build little snippets 
  of machine code dynamically.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;These snippets are used to glue together 
  pieces of JITted code, or to check security, or twiddle the calling 
  convention, or various other reasons.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;If the circumstances of creation are rare 
  enough, we might not even synchronize threads that are building these 
  snippets.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;Instead, we might use a light-weight atomic compare/exchange 
  instruction to install the snippet.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Losing the race means we must discard the 
  extra snippet.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;But if the snippet is small enough, the race is unlikely enough, and 
  the leak is bounded enough (e.g. we only need one such snippet per AppDomain 
  or process and reclaim it when the AppDomain or process terminates), then 
  leaking is perfectly reasonable.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;In that case, we may have allocated the 
  snippet in a heap that doesn’t support free’ing. &lt;/FONT&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l11 level1 lfo12; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;This 
  approach certainly encourages a lot of messy code inside the 
  DLL_PROCESS_DETACH notification – which we all know is a very dangerous place 
  to write code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;This is particularly true, given the way threads are wacked by the OS 
  at arbitrary points of execution.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Sure, all the OS CRITICAL_SECTIONs have 
  been weakened.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;But all the other synchronization primitives are still owned by those 
  wacked threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
  &lt;/SPAN&gt;And the weakened OS critical sections were supposed to protect data 
  structures that are now in an inconsistent state.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If your shutdown 
  code wades into this landmine of deadlocks and trashed state, it will have a 
  hard time cleanly releasing memory blocks.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Projects often deal with this case by 
  keeping a count of all locks that are held.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;If this count is non-zero when we get our 
  DLL_PROCESS_DETACH notification, it isn’t safe to perform leak detection.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But this leads to 
  concerns about how often the leak detection code is actually executed.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For a while, we 
  considered it a test case failure if we shut down a process while holding a 
  lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
  that was an insane requirement that was often violated in race 
  conditions.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l11 level1 lfo12; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;The OS is 
  about to reclaim all resources associated with this process.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OS will 
  perform a faster and more perfect job of this than the application ever 
  could.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;From 
  a product perspective, leak detection at product shutdown is about the least 
  interesting time to discover leaks.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l11 level1 lfo12; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2 
  &gt;DLL_PROCESS_DETACH notifications are delivered to 
  different DLLs in a rather arbitrary order.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;I’ve seen DLLs either depend on brittle 
  ordering, or I’ve seen them make cross-DLL calls out of their DllMain in an 
  attempt to gain control over this ordering.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;This is all bad practice.&lt;SPAN 
  style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, I must 
  admit that in V1 of the CLR, fusion.dll &amp;amp; mscorwks.dll played this “dance 
  of death” to coordinate their termination.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;Today, we’ve moved the Fusion code into 
  mscorwks.dll.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l11 level1 lfo12; tab-stops: list .5in" 
  &gt;&lt;FONT face=Tahoma size=2&gt;I think 
  it’s too easy for developers to confuse all the discipline surrounding this 
  approach with actually being leak-free.&lt;SPAN style="mso-spacerun: yes" 
  &gt;&amp;nbsp; &lt;/SPAN&gt;The approach is so onerous that the goal 
  quickly turns into satisfying the requirements rather than chasing 
  leaks.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;There are at least two other ways to 
track leaks.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;One way is to identify scenarios that 
can be repeated, and then monitor for leaks during the steady-state of repeating 
those scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;For example, we have a test harness which can create an AppDomain, load 
an application into it, run it, unload the AppDomain, then rinse and 
repeat.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
first few times that we cycle through this operation, memory consumption 
increases.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;That’s because we actually JIT code and allocate data structures to 
support creating a 2&lt;SUP&gt;nd&lt;/SUP&gt; AppDomain, or support 
making remote calls into the 2&lt;SUP&gt;nd&lt;/SUP&gt; AppDomain, or 
support unloading that AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;More subtly, the ThreadPool might create – 
and retain – a waiter thread or an IO thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or the application may trigger the creation 
of a new segment in the GC heap which the GC decides to retain even after the 
incremental contents have become garbage.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This might happen because the GC decides it 
is not productive to perform a compacting collection at this time.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even the OS heap 
can make decisions about thread-relative look-aside lists or lazy VirtualFree 
calls.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;But if you ignore the first 5 cycles of 
the application, and take a broad enough view over the next 20 cycles of the 
application, a trend becomes clear.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And if you measure over a long enough period, 
paltry leaks of 8 or 12 bytes per cycle can be discovered.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Indeed, V1 of the 
CLR shipped with a leak for a simple application in this test harness that was 
either 8 or 12 bytes (I can never remember which).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of that, 4 bytes 
was a known leak in our design.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It was the data structure that recorded the 
IDs of all the AppDomains that had been unloaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I don’t know if we’ve subsequently addressed 
that leak.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
in the larger scheme of things, 8 or 12 bytes is pretty impressive.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Recently, one of our test developers has 
started experimenting with leak detection based on tracing of our unmanaged data 
structures.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Fortunately, many of these internal data structures are already described 
to remote processes, to support out-of-process debugging of the CLR.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The idea is that we 
can walk out from the list of AppDomains, to the list of assemblies in each one, 
to the list of types, to their method tables, method bodies, field descriptors, 
etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we 
cannot reach all the allocated memory blocks through such a walk, then the 
unreachable blocks are probably leaks.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Of course, it’s going to be much harder 
than it sounds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;We twiddle bits of pointers to save extra state.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We point to the 
interiors of heap blocks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We burn the addresses of some heap blocks, 
like dynamically generated native code snippets, into JITted code and then 
otherwise forget about the heap address.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So it’s too early to say whether this 
approach will give us a sound mechanism for discovering leaks.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it’s certainly 
a promising idea and worth pursuing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Rambling Security 
Addendum&lt;o:p&gt;&lt;/O:P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Finally, an off-topic note as I close 
down:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I haven’t blogged in about a month.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because I 
spent over 2 weeks (including weekends) on loan from the CLR team to the DCOM 
team.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 
you’ve watched the tech news at all during the last month, you can guess 
why.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s 
security.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;From outside the company, it’s easy to 
see all these public mistakes and take a very frustrated attitude.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;“When will 
Microsoft take security seriously and clean up their act?”&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I certainly 
understand that frustration.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And none of you want to hear me whine about 
how it’s unfair.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;The company performed a much publicized 
and hugely expensive security push.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Tons of bugs were filed and fixed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;More importantly, 
the attitude of developers, PMs, testers and management was fundamentally 
changed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Nobody on our team discusses new features without considering security 
issues, like building threat models.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Security penetration testing is a fundamental 
part of a test plan.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Microsoft has made some pretty strong 
claims about the improved security of our products as a result of these 
changes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And 
then the DCOM issues come to light.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Unfortunately, it’s still going to be a 
long time before all our code is as clean as it needs to be.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Some of the code we reviewed in the DCOM 
stack had comments about DGROUP consolidation (remember that precious 64KB 
segment prior to 32-bit flat mode?) and OS/2 2.0 changes.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some of these 
source files contain comments from the ‘80s.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I thought that Win95 was ancient!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I’ve only been at Microsoft for 6 
years.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But 
I’ve been watching this company closely for a lot longer, first as a customer at 
Xerox and then for over a decade as a competitor at Borland and Oracle.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For the greatest 
part of Microsoft’s history, the development teams have been focused on enabling 
as many scenarios as possible for their customers.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s only been for 
the last few years that we’ve all realized that many scenarios should never be 
enabled.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And 
many of the remainder should be disabled by default and require an explicit 
action to opt in.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;One way you can see this change in the 
company’s attitude is how we ship products.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The default installation is increasingly 
impoverished.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;It takes an explicit act to enable fundamental goodies, like 
IIS.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Another hard piece of evidence that 
shows the company’s change is the level of resource that it is throwing at the 
problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Microsoft has been aggressively hiring security experts.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Many are in a new 
Security Business Unit, and the rest are sprinkled through the product 
groups.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Not 
surprisingly, the CLR has its own security development, PM, test and penetration 
teams.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I certainly wasn’t the only senior 
resource sucked away from his normal duties because of the DCOM alerts.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Various folks from 
the Developer Division and Windows were handed over for an extended period.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One of the other 
CLR architects was called back from vacation for this purpose.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;We all know that Microsoft will remain a 
prime target for hacking.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There’s a reason that everyone attacks 
Microsoft rather than Apple or Novell.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This just means that we have to do a lot 
better.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;Unfortunately, this stuff is still way 
too difficult.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;It’s a simple fact that only a small percentage of developers can write 
thread-safe free-threaded code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And they can only do it part of the 
time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
state of the art for writing 100% secure code requires that same sort of 
super-human attention to detail.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And a hacker only needs to find a single 
exploitable vulnerability.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I do think that managed code can avoid 
many of the security pitfalls waiting in unmanaged code.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Buffer overruns are 
far less likely.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Our strong-name binding can guarantee that you call who you think you are 
calling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Verifiable type safety and automatic lifetime management eliminate a 
large number of vulnerabilities that can often be used to mount security 
attacks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Consideration of the entire managed stack makes simple luring attacks 
less likely.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Automatic flow of stack evidence prevents simple asynchronous luring 
attacks from succeeding.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And so on.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;But it’s &lt;I 
style="mso-bidi-font-style: normal"&gt;still&lt;/I&gt; way too 
hard.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Looking 
forwards, a couple of points are clear:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;1)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;We need to focus harder on the goal that 
managed applications are secure, right out of the box.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means 
aggressively chasing the weaknesses of our present system, like the fact that 
locally installed assemblies by default run with FullTrust throughout their 
execution.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It 
also means static and dynamic tools to check for security holes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.25in"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal 
style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo5; tab-stops: list .5in"&gt;&lt;SPAN 
style="mso-fareast-font-family: Tahoma; mso-bidi-font-family: Tahoma"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT 
face=Tahoma size=2&gt;2)&lt;/FONT&gt;&lt;SPAN 
style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT 
face=Tahoma size=2&gt;No matter what we do, hackers will find 
weak spots and attack them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The very best we can hope for is that we can 
make those attacks rarer and less effective.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT 
face=Tahoma size=2&gt;I’ll add managed security to my list for 
future articles.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/O:P&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51504" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item><item><title>TransparentProxy</title><link>http://blogs.msdn.com/b/cbrumme/archive/2003/07/14/51495.aspx</link><pubDate>Mon, 14 Jul 2003 22:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:51495</guid><dc:creator>cbrumme</dc:creator><slash:comments>27</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/cbrumme/rsscomments.aspx?WeblogPostID=51495</wfw:commentRss><comments>http://blogs.msdn.com/b/cbrumme/archive/2003/07/14/51495.aspx#comments</comments><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One of 
the recurring requests for a blog is related to TransparentProxy, RealProxy, 
Contexts, Interception, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As 
usual, I’m typing this where I don’t have access to our corporate network and 
the sources, so some details might be a little off.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(When will my dentist provide free 
wireless to his customers?)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And, as 
usual, none of this is going to help you in developing applications.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, I postponed writing about this 
topic – despite all the requests – because it seems so obscure.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if you are struggling through the 
Rotor source base, it might explain some of the code that you see.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I say ‘might’ because I’ve never 
actually looked at the Rotor sources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;I’m just relying on the fact that they are a pretty faithful of a 
cleansed snapshot of our desktop CLR sources.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Anyway…&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Normally, a reference to a managed object is just that: a native memory 
pointer.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is reported 
accurately to the GC so that we can track reachability and so we can update that 
pointer if the object is relocated during a compaction.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But in the case of an object that 
derives from MarshalByRefObject (MBRO), it’s possible that the object instance 
is actually remote.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If this is the 
case, a proxy stands in for the server instance.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The TP / RP 
Pair&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In fact, 
we don’t have a single proxy for this case.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, we have a proxy pair.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This pair consists of a 
System.Runtime.Remoting.Proxies.__TransparentProxy (TP) and a RealProxy 
(RP).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The client calls on the TP; 
the TP forwards the calls to the RP; the RP usually delivers calls to a remote 
server object via a channel.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I say 
‘usually’ because the RP can actually do whatever it wants.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There doesn’t even have to be a remote 
server object if you have a clever enough RP.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Why 
would we have both a TP and an RP?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Clearly there’s a performance penalty associated with using two 
proxies.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have to instantiate 
them both and we force calls to take a doubly-indirected path.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This overhead is necessary because the 
TP and RP are for different reasons:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The TP 
is pure magic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Its job is to fool 
all the CLR code that performs casting, field access, method dispatch, etc. into 
thinking that it’s dealing with a local instance of the appropriate type.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In contrast, the RP has absolutely no 
magic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Its job is to provide an 
extensibility point where we can define RemotingProxy, or 
YourOwnProtocolProxy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It simply 
isn’t possible for us to combine magic with extensibility on the same object, as 
we shall see.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So how 
does the TP work its magic?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Throughout the code base, whenever we are making type-based decisions 
(like GetType(), castclass &amp;amp; isinst IL opcodes), we’re careful to consider 
the TP type’s special ability to stand in for other types.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In our method dispatch pathways, we are 
always careful to tease out the cases where a TP might lie in the callpath and 
deliver the calls to that object rather than optimizing the dispatch.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whenever we are accessing fields, 
creating byrefs, or otherwise referring to instance state, we ensure that these 
operations are delivered to the TP in a virtualized way.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Let’s 
look at these operations in more detail.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In the discussion that follows, we are only interested in operations on 
potentially remote instances.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Potentially remote instances include:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in" 
 &gt;&lt;FONT 
  face=Tahoma size=2&gt;The MBRO type and all types that derive from it, including 
  ContextBoundObject (CBO) and __ComObject.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in" 
 &gt;&lt;FONT 
  face=Tahoma size=2&gt;Interface methods, since these interfaces could be 
  implemented on a MBRO type.&lt;/FONT&gt; 
  &lt;LI class=MsoNormal 
  style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in" 
 &gt;&lt;FONT 
  face=Tahoma size=2&gt;All methods of Object since, by widening, a remote MBRO 
  instance could be passed around formally as Object.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Significantly, types in the hierarchy below Object and disjoint from MBRO 
can never be remoted.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this 
portion of the hierarchy, which contains the vast majority of all types and 
includes all array types, we are free to inline methods, perform direct field 
access, perform calls without indirecting stubs, take byrefs, etc., without any 
consideration for remoting overheads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;As I explained in a prior blog, this is why we don’t allow you to use a 
marker interface to indicate remotability – it must be boiled into the 
singly-inherited hierarchy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Otherwise, widening would prevent us from applying optimizations like 
direct field access to anything but sealed classes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT 
size=2&gt;Statics&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In an 
earlier blog, I already explained why we never remote static members.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Static members don’t involve a ‘this’, 
so they completely bypass the proxy and proceed like local calls.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT 
size=2&gt;Virtuals&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When the 
CLR is using VTables for virtual dispatch, all it needs to do is construct a 
VTable for the TP class that is at least as long as the longest VTable loaded by 
any type in the process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We do this 
by reserving enough virtual memory for the longest legal VTable, and then we 
commit and prepare pages of this VTable as required by dynamic class loads of 
other proxyable types.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Slot ‘n’ of 
this VTable does something like “PUSH n; JMP CommonStub”.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, the purpose of this 
VTable is to capture which slot was called through and then perform some common 
processing on it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ll explain the 
common processing later.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I’ve 
also implied that the CLR might not use VTables for virtual dispatch.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Hopefully it’s obvious that most of what 
I discuss is specific to a particular implementation of the CLR.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Almost all of these details can change 
from release to release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And I 
would expect them to be very different in other implementations of the CLI.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whether the CLR continues to use VTables 
in a future release is a different rat-hole.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
the great thing about the virtual case is that the test for whether something is 
local or remote is completely hidden in the normal indirection of a virtual 
dispatch.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are no additional 
penalties.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT 
size=2&gt;Non-virtuals&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Bashing 
VTables is a fairly standard technique.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But non-virtual methods aren’t generally called through 
indirections.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are some 
exceptions to this rule, like NGEN cross-assembly calls and JITted calls to 
methods that haven’t yet themselves been JITted.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, in the typical case, we make 
non-virtual calls direct to the target method, just like static calls.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even when C# emits a ‘callvirt’ IL 
opcode to target a non-virtual method, this just forces us to check that the 
‘this’ is non-null, as we’ve seen in an earlier blog (e.g. ‘mov eax, 
[ecx]’).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we are dispatching on a 
TP instead of a local instance, this non-null check isn’t going to help us 
capture the call.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Instead, 
for every non-virtual call on a potentially remote instance, we go through a 
special stub.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This stub is 
constructed on-demand for a specific remoted method body and is then cached in 
case we find other callsites that need it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The purpose of the stub is to quickly check whether the server object is 
local to the calling thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
details of this test depend on exactly what might be proxied.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of a normal MBRO, we’re just 
interested in whether the client’s reference is to a TP or to a local 
instance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the case of a CBO, the 
client’s reference is always to a TP.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;So in that case we are interested in whether the thread is already in the 
server’s context or whether a context transition must be performed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;More on &lt;I 
style="mso-bidi-font-style: normal"&gt;this &lt;/I&gt;later, too.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Virtuals 
called non-virtually&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In an 
earlier blog, we saw how it’s possible to call virtuals in a non-virtual 
fashion.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This supports C#’s ‘base’ 
calls and the more flexible scope override operator ‘::’ of Managed C++.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, these cases are relatively 
rare.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Virtual methods are almost 
always called virtually.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Anyway, we 
handle non-virtual calls to potentially remote virtual methods by lazily 
creating and caching stubs as in the non-virtual method case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT 
size=2&gt;Interfaces&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;You 
might think that interfaces would be handled just like virtual calls, since we 
place the interface methods into each type’s VTable during class layout.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, the necessities of efficient 
interface dispatch cause some additional problems.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s side-track on how interfaces work, 
for a moment.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The same 
interface can be implemented on multiple different classes.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each class will contain the methods for 
the interface contract at possibly different places in its VTable.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The callsite is polymorphic with respect 
to the class of the server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So our 
goal is for the dispatch to discover, as quickly as possible, where the 
appropriate interface methods can be discovered on the receiver’s class.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(There are other ways of performing 
interface dispatch that finesse this goal, like using fat pointers or interface 
proxy instances.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Those other 
techniques have their own problems.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And this is a blog on TP / RP, not interfaces, so let’s stick with the 
goal that I’ve stated).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;We’re 
currently on our 4&lt;SUP&gt;th&lt;/SUP&gt; implementation of interface dispatch.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The implementation that’s in the Rotor 
sources and was shipped in V1 and V1.1 was our 3&lt;SUP&gt;rd&lt;/SUP&gt; 
implementation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that design, 
every interface is assigned a unique interface number during loading.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each class that implements one or more 
interfaces has a secondary interface table or ITable which is available via an 
indirection from the standard VTable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Dispatch occurs by indirecting through this ITable using the interface 
number of the interface.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This 
points us back to a section of normal VTable (usually within the receiver’s 
normal class VTable somewhere) where the interface’s methods are laid out.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, the ITable is incredibly 
sparse.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A given class might 
implement just the interfaces numbered 1003 and 2043.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We only need two slots for that class, 
so it would be extremely wasteful to burn 2044 slots.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Therefore a key aspect of this design is 
that the ITables are all allocated sparsely in a single shared heap.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s important to find an algorithm that 
can efficiently pack all the ITables for all the classes we have loaded, without 
forcing our class loader to solve a “knapsack” problem.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The 
above works well for normal types, which each implement a bounded set of 
interfaces.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the TP class needs 
to implement all interfaces because it must stand in for all possible 
classes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a similar way, the 
__ComObject class must implement all interfaces on all RCWs.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because a QueryInterface on some 
instance of a particular RCW type might one day say “Yes, I implement that 
interface.”&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(By the end of this 
blog you will know why __ComObject isn’t just a TP with a specialized RP 
implementation that understands COM rules).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Here’s 
what a virtual dispatch might look like on X86, with a shipping version of the 
CLR.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;mov&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;eax, [ecx]&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;; get the VTable 
from ‘this’&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;call [eax+mslot*4]&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;; call through 
some slot&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And 
here’s an equivalent interface dispatch, which shows the indirection through the 
ITable.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;mov&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;eax, [ecx]&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;; get the VTable 
from ‘this’&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;mov&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;eax, [eax+j]&lt;SPAN 
style="mso-tab-count: 1"&gt; &lt;/SPAN&gt;&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;; get the ITable 
at some offset from it&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;mov&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;eax, [eax+islot*4]&lt;SPAN 
style="mso-tab-count: 1"&gt; &lt;/SPAN&gt;; get the right interface 
VTable&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;call [eax+mslot*4]&lt;SPAN 
style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;; call through 
some slot&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Leaving 
aside all the cache faults that might cripple us, the interface dispatch looks 
pretty good.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s just a couple 
more instructions than the virtual dispatch.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And we certainly don’t want to slow down 
this great interface dispatch for our typical case, in order to support the 
unbounded nature of TP and __ComObject interface dispatch.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we need a data structure for TP that 
will work for all potentially remote types and all the interfaces.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The solution is to have a single ITable 
for these cases, which is fully populated with all the interfaces we have ever 
loaded.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously we have to grow 
this by committing more memory as the application faults in more 
interfaces.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And each entry in the 
ITable points to a bit of VTable representing the appropriate interface, where 
the slots are full of stubs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
stubs contain machine code that says something like “If my ‘this’ is a TP, go do 
the remoting stuff.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Otherwise my 
‘this’ better be a __ComObject of some kind and I must go do the COM Interop 
stuff.”&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We actually use the VTables 
of the interface types themselves (which otherwise would contain nothing 
interesting in their slots) for this purpose.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
are struggling to understand interface dispatch in the Rotor sources, the above 
might provide some useful guidance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The bad news is that we have switched to a somewhat different technique 
in our current codebase.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, 
I can’t predict when this new technique will ship in a CLR product or when it 
might show up in a new Rotor drop.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT 
size=2&gt;Constructors&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Constructors are like non-virtual calls, except for the twist that – when 
they are mentioned in a ‘newinst’ IL opcode rather than a ‘call’ or ‘callvirt’ 
IL opcode – they involve an object allocation.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In remoting scenarios, it’s clearly 
important to combine the remote allocation with the remote execution of the 
instance constructor method to avoid a 2&lt;SUP&gt;nd&lt;/SUP&gt; round-trip.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Instance 
Field Access and Byrefs&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If a 
type cannot be remoted, all field access is direct.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The X86 JIT tends to produce tight code 
like ‘mov eax, [ecx+34]’ if it is loading up a field.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But this clearly won’t work if a TP is 
involved.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, the field access 
is turned into an implicit property access that can be remoted.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s great for the case where the 
server truly is remote.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it’s an 
unfortunate penalty for the case where the server is local and was only 
potentially remote.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In the 
case of a byref, once again the JIT is normally efficient (e.g. ‘lea eax, 
[ecx+34]’).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You might imagine that 
we could virtualize the byref the way we virtualize the implicit property 
access.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other words, we could 
generate a secret local and prime it with the value of the field (umm, 
property).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then we could make the 
call with a byref to the local as the argument.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the call returns, we could 
back-propagate the – perhaps updated – value of the local back into the 
field/property.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The machinery to do 
this is relatively straight-forward.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But it breaks the aliasing assumptions of byrefs.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if you were to update the 
field through the byref and then examine the server before unwinding the stack, 
the byref modification would not have been propagated back to the server object 
yet.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For 
better or for worse, the current implementation doesn’t go this route.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, the CLR allows you to take a 
byref to a field of a potentially remote object if that object is in fact 
local.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it throws an exception 
if you attempt to take such a byref on a potentially remote object that is 
indeed remote.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In 
passing, I should mention that some languages, like C#, won’t allow you to even 
attempt to take a byref on a potentially remote object (subjecting yourself to 
exceptions if the server is indeed remote).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, they force the developer to 
explicitly create the local, pass a byref to that local, and perform the 
back-propagation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This way there’s 
no magic and the developer understands exactly when and how his values get 
updated.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And I 
should also point out that if you call a method on a remote MBRO server, passing 
a byref to a field of a non-MBRO local object or to a static field or to a 
local, that same aliasing issue can be observed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that case, we decided it was okay to 
allow observable aliasing discrepancies until the stack unwinds and the byref 
back-propagation can occur.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Casting, 
progressive type refinement&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So far, 
I’ve been a little sloppy with the term VTable.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Managed objects actually have a 
MethodTable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The MethodTable is 
currently implemented to have some GC info growing at a negative offset from the 
MethodTable (to tell the GC where all the pointers are for tracing), some “hot” 
metadata, and then a VTable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Part 
of the “hot” metadata is a parent pointer so we can traverse up the 
single-inheritance hierarchy and a list of implemented interfaces so we can 
perform interface casting.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So 
normally all our type tests are based on the MethodTable of the instance.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the TP has a rather uninteresting 
parent pointer (System.Object) and an empty list of implemented interfaces.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that all of the type checks 
tend to fail.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the failure path, 
right before we throw an exception, we say “Oh, is this one of those weird cases 
like TP or __ComObject?”&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If it is, 
we vector off to an appropriate routine that understands how to perform 
QueryInterface calls or ManagedRemoting calls or whatever is appropriate for 
each case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unless the Rotor source 
cleansing process performed a rename, there’s probably a routine in 
JITInterface.cpp called JITutil_CheckCastBizarre that’s an example of how we 
handle these weird cases.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that 
they are typically placed into the failure paths, so the requirements of 
remoting don’t impact the performance of the local cases.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For the 
cases where we have a CBO, we can trivially know the exact type of the server 
instance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Everything is loaded in 
the same process and we can encode the server’s type with a MethodTable in the 
normal fashion.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if the client 
and server are in different AppDomains, processes, or machines then type 
injection becomes a consideration.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In an earlier blog, I’ve talked about the security threats that depend on 
injecting an assembly into someone else’s AppDomain.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, it may be possible for an 
assembly to escape the restrictive security policy of one AppDomain by injecting 
itself into the host’s AppDomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Furthermore, inadvertent type injection across an AppDomain boundary can 
interfere with a host’s ability to discard types through AppDomain 
unloading.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s why we return an 
ObjectHandle from the various AppDomain.CreateInstance and CreateInstanceFrom 
overloads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You must explicitly 
unwrap the ObjectHandle or use a CreateInstanceAndUnwrap convenience helper, to 
opt-in to the injecting behavior.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Another 
mechanism that helps you control type injection is ‘progressive type 
refinement’.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This mechanism 
leverages the ability of a TP to stand-in for all different types.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When you marshal back a remote MBRO, a 
TP is created in the client’s Context and AppDomain.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(The Context is typically the default 
Context for the AppDomain, unless you are using CBOs).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Consider the following code 
fragments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;AppDomain ad = 
…;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;Object o = 
ad.CreateInstanceAndUnwrap(…);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;SomeIface i = (SomeIface) 
ad.CreateInstanceAndUnwrap(…);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;SomeClass c = (SomeClass) 
ad.CreateInstanceAndUnwrap(…);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;o:p&gt;&lt;FONT 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;Type t = 
c.GetType();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So long 
as the object we create in the remote AppDomain ‘is-a’ MBRO, the result of 
executing CreateInstanceAndUnwrap() will be a TP that masquerades as an instance 
of type System.Object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we then 
cast the unwrapped object to SomeIface, our program obviously has mentioned that 
type in an early-bound manner in the client’s AppDomain.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So that type is already present and 
doesn’t need to be injected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the 
remote object can indeed be cast to SomeIface, the TP will refine its notion of 
the remote server’s type so that it includes SomeIface.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a similar fashion, the TP can be 
refined to understand that it is-a SomeClass – and all the super-classes and 
implemented interfaces of SomeClass.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Unfortunately, calls like c.GetType() terminate our ability to limit the 
type knowledge in the client’s Context / AppDomain.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you actually ask for the fully 
derived type of the remote concrete instance, we must obtain that remote type 
and attempt an injection of it into the client’s Context.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, for constrained patterns of 
calls, it’s possible for the host to get some real benefits from this 
feature.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Clearly 
we can only support progressive type refinement on objects that marshal by 
reference with a TP.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Objects that 
marshal by value will necessarily inject the full type of the concrete instance 
that is produced during the unmarshal.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So we’ve 
seen how TP intrudes in the normal processing of calls, field access, and type 
checking.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Now we 
can understand the reasons why the TP and RP must be separated.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any call on the TP is captured into a 
message object and forwarded to the RP.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The RP author (either our Managed Remoting team or you as a 
3&lt;SUP&gt;rd&lt;/SUP&gt; party extension) now wants to operate on that message.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Any methods and fields you define for 
this purpose must necessarily be on a different type than the TP.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If they were defined on the TP, they 
would be subject to the same capture into a message.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We would never get any work done until 
the consequent infinite recursion blows the stack.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;There’s 
a small lie in the above.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We 
actually have a few methods that are exempt from this automatic “capture and 
forward.”&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Object.GetHashCode(), 
when it isn’t overridden by the remotable subtype, is an example.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But if we wanted to allow you to add 
arbitrary methods, fields and interfaces to your RP implementation, we would 
have an impossible mess of ambiguities.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Slot 23 in the TP’s VTable would somehow be a captured call for every 
remotable type in the system &lt;I style="mso-bidi-font-style: normal"&gt;and&lt;/I&gt; a 
necessary local execution of some RP behavior on that captured call.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Along 
the same lines, any call to GetType() or use of the castclass and isinst IL 
opcodes would be ambiguous if we merged the TP and RP.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We wouldn’t know if we should deliver 
the TP semantics of pretending to be the remote server’s type, or whether we 
should deliver the RP semantics of your extensibility object.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The Common 
Stub&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Let’s go 
back to the stubs in the VTable of the TP, which capture virtual calls.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I already said that they look like “PUSH 
‘n’; JMP CommonStub”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The common 
stub has to somehow convert the small integer in EAX into something more useful 
– the MethodDesc of the target method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;(A MethodDesc is an abbreviation for method descriptor.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s the piece of internal metadata that 
uniquely describes each method, including its metadata token, how to generate 
code for it, where the generated code can be found, the signature of the method, 
the MethodTable that contains it, and any special information like PInvoke 
marshaling or COM Interop information.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;We encode this pretty tightly and it usually fits into 32 
bytes).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;All 
virtual methods are instance methods, so we can use the ‘this’ of the call to 
help us obtain the desired MethodDesc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;In the case of X86, we currently pass ‘this’ in ECX.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So all we need to do is find the ‘n’th 
virtual method in the VTable of the type of the instance in ECX.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Something similar can happen in the interface dispatch case.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Recall that we end up in a stub that 
hangs off the interface type’s VTable rather than the receiving class’ 
VTable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So this stub can trivially 
deliver up the relevant MethodDesc.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;And for 
the non-virtual methods (and virtual methods called non-virtually), it’s even 
easier.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In each case, we create a 
stub that is specific to that method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;So this stub can contain the MethodDesc as an immediate argument burned 
into its code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This 
means that all the method dispatch scenarios can obtain a MethodDesc and then 
jump to a common location.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That 
common location now has enough information to capture all the arguments into a 
System.Runtime.Remoting.Messaging.Message which can disassociate itself from the 
stack for asynchronous or cross-process remoting.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Or it can just use that information to 
efficiently access the registers and stack locations containing the arguments of 
the call, for the case where the interception remains inside the same 
process.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Unfortunately, we don’t take advantage of that 2&lt;SUP&gt;nd&lt;/SUP&gt; faster 
option as much as we should in V1 and V1.1.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have plenty of evidence that calls on 
TPs could be significantly faster in cross-Context and cross-AppDomain scenarios 
if we teased them apart from the more general remoting codepaths.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By “significantly faster”, I mean at 
least one order of magnitude for some common and important cases.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s likely that you’ll see at least 
some improvement here in our next release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And it’s also likely that even in our next release we will have ignored 
significant performance opportunities.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One 
surprising fact is that this is also why Delegate.BeginInvoke / EndInvoke are so 
slow compared to equivalent techniques like ThreadPool.QueueUserWorkItem (or 
UnsafeQueueUserWorkItem if you understand the security implications and want to 
be really efficient).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The codepath 
for BeginInvoke / EndInvoke quickly turns into the common Message processing 
code of the general remoting pathway.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;That’s fine if you are making asynchronous calls on remote objects via a 
delegate.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that case, we can 
avoid the extra context switch that would occur if we didn’t coordinate the 
remoting code with the async code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;We are careful to initiate the remote operation synchronously on the 
caller’s thread if that’s the case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But it means that the local case is dramatically slower than it needs to 
be.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, when it comes to 
performance we have much more glaring and general purpose issues to address 
before this one bubbles to the top of our list.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Finally, 
when we convert fields to implicit properties for the purposes of remoting, 
there is no corresponding MethodDesc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The method doesn’t exist anywhere in metadata.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, we go through a different 
pathway and use the FieldDesc as the piece of metadata to guide us.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The 
Hierarchy&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Here’s 
the bit of the inheritance hierarchy which pertains to this blog:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Object&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;Interfaces&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;|&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;|&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;MarshalByRefObject&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;/&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;\&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;/&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;\&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;__ComObject&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;ContextBoundObject&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;|&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;|&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN 
style="FONT-FAMILY: 'Lucida Console'"&gt;&lt;FONT size=2&gt;&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/SPAN&gt;ServicedComponent&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;As we’ve 
seen, Object and all Interfaces are potentially remote.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have to disable some optimizations to 
account for this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But anything 
which derives from Object and which does not derive from MBRO can have all 
optimizations enabled.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Remoting 
cannot be a consideration for that portion of the hierarchy.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;For MBRO 
and for classes that derive from MBRO but do not derive from CBO, we have an 
opportunity to add back an optimization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;If we are operating on ‘this’ in a method of such a type, then we know 
that the instance is now local.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 
reasoning is that if the instance were indeed remote, then the TP should have 
forwarded the call elsewhere.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since 
that didn’t happen, we can add back all the local optimizations like direct 
field access.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Under 
CBO, the situation is a little worse.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;For various reasons that are all internal implementation details, we 
currently don’t unwrap CBO.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even 
when a thread is executing inside the correct Context and the instance is in 
that sense local, we leave it as the remote case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Incidentally, we actually implemented CBO the other way first, where each 
call into a CBO would rigorously marshal the arguments via wrapping / unwrapping 
between server instances and TPs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;But this caused terrible performance problems when performing identity 
comparisons of instances typed as some Interface or as System.Object.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Simple operations like the fetch of a 
System.Object out of an Object[] required marshaling checks for the correct 
Context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We were penalizing typical 
programming operations for non-Context programming, in order to get a 
performance benefit if Contexts were indeed used.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This was a poor trade-off and we adopted 
the current plan.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Of course, 
leaving aside observable performance differences, either technique delivers the 
same semantics.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In my 
opinion, the primary benefit of the CLR is that the semantics of your program 
have been largely divorced from the details of execution.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We could change practically everything 
I’ve described in this blog, without affecting your program’s 
behavior.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Anyway, 
we currently have one trick up our sleeve for adding back performance to 
CBO.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the JIT notices that you 
are performing a lot of field access on ‘this’, it creates an unwrapped 
temporary alias for ‘this’.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then it 
performs direct field access against the alias, rather than going through the 
remoting abstraction that converts the field accesses into property 
accesses.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Clearly we could pursue 
some other optimizations here, too.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So does 
this explain why cross-AppDomain and cross-Context calls are so slow?&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We know that we have to create 
additional instances for proxying (the TP and RP).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We know that the callpaths contain 
various indirections in the form of stubs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;And we know that field access and method inlining and other standard 
optimizations are sometimes disabled because the server object is potentially 
remote.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;With our 
current design, all these overheads seem unavoidable.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But the real reason that cross-AppDomain 
and cross-Context operations are so slow is not due to these unavoidable 
overheads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s really that we 
simply haven’t invested enough engineering effort to make them faster.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We could retain our existing design and 
do a much better job of separating the “same address space” cases from the 
“different address space” cases.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As 
I’ve said, I think you’ll see some of these improvements in our next 
release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But we will still have a 
long way to go.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;__ComObject 
and ServicedComponent&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;__ComObject derives from MBRO.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;It captures calls, intrudes on type negotiations, involves remoted 
instantiation, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It must be 
using TP and RP for all this magic, right?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Actually, no.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;I hinted 
at this when I described the stub that performs interface dispatch on TPs and 
__ComObjects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The stub we build on 
the first call to a particular interface method checks whether the server is a 
TP or whether it is a __ComObject and then it bifurcates all processing based on 
this.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you 
look at the JITutil_CheckCastBizarre() routine I mentioned earlier, you see 
something similar.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The code checks 
to see if it has a TP and it checks for __ComObject separately, with bifurcated 
processing for the two cases.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This is 
all historical.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We built COM 
Interop before we realized we needed to invest in a strong managed remoting 
story that was distinct from DCOM.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;If we were to build the two services again today, we would definitely 
merge the two.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The TP/RP remoting 
code is the correct abstraction for building services like COM Interop.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And, indeed, if we had taken that 
approach then we would have been forced to address some of the “same address 
space” performance problems with managed remoting as a consequence of achieving 
our COM Interop performance goals.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This 
historical artifact is still more evident when you look at 
ServicedComponent.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In some sense, 
ServicedComponent is a COM Interop thing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;It’s a managed object that is aware of COM+ 1.0 unmanaged contexts (which 
are implemented in OLE32.dll on Win2000 and later OS’es).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As such, it delegates creation of these 
managed objects through CoCreateInstance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Whenever we call on a ServicedComponent instance, we check whether we are 
in the correct COM+ 1.0 context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If 
we are not, we call through a COM+ service to transition into the correct 
context which then calls us back.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Yet 
ServicedComponent is built on top of all the TP / RP infrastructure, rather than 
on top of __ComObject.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The reason 
for this is simply that we added EnterpriseServices and ServicedComponent very 
late in our V1 cycle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At that 
point, both the __ComObject pathway and the TP / RP pathway were available to 
us.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The TP / RP pathway is simply a 
much cleaner and more general-purpose abstraction for this sort of 
thing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If we 
ever go back and re-implement COM Interop, there are several important things we 
would change.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;First, 
we would put COM Interop onto the TP / RP plan.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Second, 
we would rewrite a lot of the COM Interop code in managed.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a long term goal for much of the 
CLR.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Frankly, it’s very hard to 
write code in the CLR without abusing the exception model, or forgetting to 
report GC references, or inadvertently performing type-unsafe operations.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All these mistakes lead to robustness 
and even security bugs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we could 
write more of the CLR in managed code, our productivity would go up and our bug 
counts would go down.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Third, 
we would replace all our COM Interop stubs with IL.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Currently, the marshaling of COM Interop 
calls is expressed in a language called ML (marshaling language).&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This was defined at a time when our IL 
was still in flux, and when we thought we would have a system of JIT-expanded 
macros that could map ML to a lower-level IL.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We ended up implementing the macro 
aspect of IL and then dropping it in order to ship V1 sooner.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This left us with the choice of either 
interpreting ML or writing converters to dynamically generate machine code from 
simple ML streams.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We ended up 
doing both.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now that IL is stable, 
and now that we are targeting multiple CPU architectures in future versions of 
the CLR (like IA64), the fact that COM Interop depends on ML is quite a 
nuisance.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;However, 
it’s not clear whether a re-implementation of COM Interop will ever be a 
sensible use of our time.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B 
style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;CBO and 
Interception&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The COM+ 
1.0 approach to call interception is very popular with MTS &amp;amp; COM+ 
programmers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Depending on your 
opinion of that product, this is either because they built a powerful 
abstraction for interception and Aspect Oriented Programming (AOP), or because 
when all you have is a hammer then everything looks like a nail.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma 
size=2&gt;Personally I think they did a great job of extending the COM model to 
include a powerful form of interception and AOP.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it’s tied up with COM-isms, like the 
fact that side effects such as transaction commit or object pooling occur when 
the last Release() call happens.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Another COM-ism is that the COM’s rules for apartment marshaling have 
been extended to apply to finer-grained contexts.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Some aspects of the COM+ model don’t 
apply well to managed code (like attaching side effects to a Release() call that 
might be delayed until a GC occurs).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Other aspects could potentially be done better in managed code, since we 
have the advantage of a strong notion of class and metadata, the ability to 
generate code on the fly, and the ability to prevent leakage across marshaling 
boundaries rather than relying on developer hygiene.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;During 
V1 of the CLR, we tried to take the great aspects of the COM+ model and adjust 
them so they would be more appropriate to the managed world.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The result is ContextBoundObject, 
System.Runtime.Remoting.Contexts.Context, and all the related classes and 
infrastructure.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Very 
briefly, all CBO instances live in Contexts.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All other managed instances are agile 
with respect to Contexts.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Calls on 
these agile instances will never trigger a Context transition.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, such instances execute methods 
in the Context of their caller.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;When a Context transition does occur, there is sufficient extensibility 
for the application or other managed code to participate in the transition.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That code can inject execution into the 
act of calling out of the caller’s Context, entering into the server’s Context, 
leaving the server’s Context when the method body completes, and returning to 
the caller’s Context.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In addition, 
there is a declarative mechanism for attaching attributes to types of CBO, 
indicating what sort of Context they should live in.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is these attributes which are 
notified as Context transitions occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;The best example of code which uses this mechanism is the 
SynchronizationAttribute class.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By 
attaching this attribute to a class that derives from CBO, you are declaring 
that any instance of your CBO should participate in a form of rental 
threading.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Only one thread at a 
time can be active inside your object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Based on whether your attribute is Reentrant or not, you can either 
select a Single Threaded Apartment-style reentrancy (without the thread affinity 
of an STA, of course) or you can select a COM+ style recursive activity-threaded 
model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Another important aspect of 
Context-based programming is that the activation or instantiation of objects can 
be influenced through the same sort of declarative interception.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;With 
this rich model, we expected CBO and managed Contexts to be a key extensibility 
point for the managed programming model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;For example, we expected to reimplement ServicedComponent so that it 
would depend on managed contexts, rather than depending on unmanaged COM+ 
contexts for its features.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, 
our biggest fear was that we would build and deliver a model for managed 
contexts which would be quickly adopted by customers, we would then reimplement 
ServicedComponent and, during that process, we would discover that our initial 
model contained some fundamental flaws. &lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;It’s always extremely risky to deliver 
key infrastructure without taking the time to build systems on top of that 
infrastructure to prove the concept.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So 
what’s our current position?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I 
don’t know the official word, but my sense is the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In the 
case of managed interception and AOP, we remain firmly committed to delivering 
on these core features.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, we 
find ourselves still debating the best way to do this.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;One 
school holds that CBO is a model which proved itself through our customers’ COM+ 
experiences, which has been delivered to customers, but which suffers from poor 
documentation and poor performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; 
&lt;/SPAN&gt;Given this, the solution is to put the appropriate resources into this 
facet of the CLR and address the documentation and performance 
problems.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Another 
school proposes that there’s an entirely different way to achieve these goals in 
the managed world.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This other 
approach takes advantage of our ability to reason about managed programs based 
on their metadata and IL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And it 
takes advantage of our ability to generate programs on the fly, and to control 
binding in order to cache and amortize some of the cost of this dynamic 
generation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Given this, the 
solution is to maintain CBO in its current form and to invest in this 
potentially superior approach.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;To be 
honest, I think we’re currently over-committed on a number of other critical 
deliverables.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the next release, 
I doubt if either of the above schools of thought will win out.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, we will remain focused on some 
of the other critical deliverables and postpone the interception decision.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s unfortunate, because I would love 
to see the CLR expose a general-purpose but efficient extensibility mechanism to 
our customers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Such a mechanism 
might eliminate some of the feature requests we are currently struggling with, 
since teams outside the CLR could leverage our extensibility to deliver those 
features for us.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma 
size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;On the 
other hand, there’s something to be said for letting a major feature sit and 
stew for a while.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve gathered a 
lot of requirements, internally and externally, for interception.&lt;SPAN 
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But I think we’re still puzzling through 
some of the implications of the two distinctly different design 
approaches.&lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51495" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/cbrumme/archive/tags/CLR/">CLR</category></item></channel></rss>