<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">cbrumme's WebLog</title><subtitle type="html" /><id>http://blogs.msdn.com/cbrumme/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/cbrumme/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2003-05-17T18:56:00Z</updated><entry><title>A quick update on me.</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2006/09/15/756709.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2006/09/15/756709.aspx</id><published>2006-09-16T01:55:00Z</published><updated>2006-09-16T01:55:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=756709" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author></entry><entry><title>Updated Finalization and Hosting</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2004/04/26/120609.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2004/04/26/120609.aspx</id><published>2004-04-27T00:58:00Z</published><updated>2004-04-27T00:58:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=120609" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author><category term="CLR" scheme="http://blogs.msdn.com/cbrumme/archive/tags/CLR/default.aspx" /><category term="Chat" scheme="http://blogs.msdn.com/cbrumme/archive/tags/Chat/default.aspx" /></entry><entry><title>Hosting</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2004/02/21/77595.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2004/02/21/77595.aspx</id><published>2004-02-21T18:28:00Z</published><updated>2004-02-21T18:28:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=77595" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author><category term="CLR" scheme="http://blogs.msdn.com/cbrumme/archive/tags/CLR/default.aspx" /></entry><entry><title>Finalization</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx</id><published>2004-02-21T06:27:00Z</published><updated>2004-02-21T06:27:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=77460" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author><category term="CLR" scheme="http://blogs.msdn.com/cbrumme/archive/tags/CLR/default.aspx" /></entry><entry><title>Apartments and Pumping in the CLR</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx</id><published>2004-02-02T19:52:00Z</published><updated>2004-02-02T19:52:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=66219" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author><category term="CLR" scheme="http://blogs.msdn.com/cbrumme/archive/tags/CLR/default.aspx" /></entry><entry><title>Access to old blogs</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2003/11/10/51572.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2003/11/10/51572.aspx</id><published>2003-11-10T20:26:00Z</published><updated>2003-11-10T20:26:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51572" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author><category term="Chat" scheme="http://blogs.msdn.com/cbrumme/archive/tags/Chat/default.aspx" /></entry><entry><title>The PDC and Application Compatibility, but still no Hosting</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2003/11/10/51554.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2003/11/10/51554.aspx</id><published>2003-11-10T20:00:00Z</published><updated>2003-11-10T20:00:00Z</updated><content type="html">&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;img src="http://blogs.msdn.com/aggbug.aspx?PostID=51554" width="1" height="1"&gt;</content><author><name>cbrumme</name><uri>http://blogs.msdn.com/members/cbrumme.aspx</uri></author><category term="CLR" scheme="http://blogs.msdn.com/cbrumme/archive/tags/CLR/default.aspx" /></entry><entry><title>The Exception Model</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx" /><id>http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx</id><published>2003-10-01T20:18:00Z</published><updated>2003-10-01T20:18:00Z</updated><content type="html">&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 0