SharePoint : Faulting application w3wp.exe

Faulting application w3wp.exe, version 6.0.3790.1830, stamp 42435be1, faulting module stswel.dll, version 11.0.6568.0, stamp 42e17544, debug? 0, fault address 0x0009310c.

This is something I fell victim about 18 months ago, pre-SP1 for Windows SharePoint Services, and I'd forgotten about until the recent release of SP2 for both WSS and SPS. By the time I had resolved the problem and discussed it with the Microsoft Escalation Engineer we had standing by, SP1 was already in testing. It was said that a "fix" may not make that service pack. So, it was worked around and was duly forgotten until now -- the release of SP2 -- and so I decided to see if it had been "fixed."

Now, I put "fix" and "fixed" in quotes because to be fair to Microsoft, the issue at hand is not quite so straightforward to repair per-se. It all stems from a particular quirk of using the IDisposable pattern: if you're given an object that implements IDisposable via a closed-source API (like SharePoint's), how do you really know for sure if you can safely Dispose() of it when you're done?

It all started when I was in the middle of a very critical global rollout (think screaming IT directors, managers sweating, staff afraid to go for toilet breaks critical) for a large multinational when I started getting directed to the webpart maintenance page on the occasional page, in a seemingly random manner. When I enabled stacktracing in the web.config file, I saw:


[WebPartPageUserException: Exception occurred.]
Microsoft.SharePoint.SPWebPartCollection.a(WebPart A_0, Boolean A_1) +423
Microsoft.SharePoint.SPWebPartCollection.a(WebPart A_0) +7
Microsoft.SharePoint.SPWebPartCollection.f(WebPart A_0) +39
Microsoft.SharePoint.SPWebPartCollection.b(WebPart A_0) +333
Microsoft.SharePoint.WebPartPages.WebPart.g() +88
Microsoft.SharePoint.WebPartPages.WebPart.bl() +266
Microsoft.SharePoint.WebPartPages.WebPart.OnUnload(EventArgs e) +92
System.Web.UI.Control.UnloadRecursive(Boolean dispose) +121
System.Web.UI.Control.UnloadRecursive(Boolean dispose) +74
System.Web.UI.Control.UnloadRecursive(Boolean dispose) +74
System.Web.UI.Control.UnloadRecursive(Boolean dispose) +74
System.Web.UI.Page.ProcessRequestCleanup() +24
System.Web.UI.Page.ProcessRequest() +218
System.Web.UI.Page.ProcessRequest(HttpContext context) +18
Microsoft.SharePoint.ApplicationRuntime.SharePointHandler.SPProcessRequest(HttpContext context) +415

[ApplicationException: Exception of type System.ApplicationException was thrown.]
Microsoft.SharePoint.ApplicationRuntime.SharePointHandler.SPProcessRequest(HttpContext context) +1073
Microsoft.SharePoint.ApplicationRuntime.SharePointHandler.SPProcessRequest(HttpContext context) +0
Microsoft.SharePoint.ApplicationRuntime.SharePointHandler.ProcessRequest(HttpContext context) +21
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute() +179
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +87


Prior to this event, I'd gone a mad optimization run: checking all objects for IDisposable (SPWeb, SPSite etc) and making sure that I was either calling Dispose in a finally clause, or wrapping the block in a using statement; avoiding dodgy concatenations; unneccesary boxing/unboxing; checking all DLLs were Release build, etc etc. The reasons for this was because our application was running slower than expected and was doing quite a lot of swapping of virtual memory. Later in the project we discovered the real problem to be a badly written navigation control that was building an in-memory XML file using the Xml DOM classes: these things are serious memory hogs -- stick to StringBuilders if you can. Back to the problem: we had three different webparts in different permutations on various pages, and eventually I narrowed it to a certain combination of webparts. This took a long, long time to isolate the code in question; here is the heart of it:

WebPart A:

using (SPWeb thisWeb = SPControl.GetContextWeb(HttpContext.Current)) {
    // do something with thisWeb object, read site name, etc...
}


WebPart B:


[WebPartStorage(Storage.Personal)]
public int Size {
    get { ... }
    set { ... }
}

public void MyMethod() {
    this.Size = 5;
    this.SaveProperties = true;
}


So, the crux of it was that if any webpart on the page calls Dispose on the context SPWeb, and another webpart (or the same one) wants to SaveProperties, we're screwed. When the page unloads and the SharePoint framework tries to serialize any changed Properties to the content database, it fails because an essential COM object has been released in the disposal process that facilitates the property serialization process. You can reproduce the crash in RTM, SP1 and SP2 of both SPS and WSS with the following:

Repro code:

protected override void RenderWebPart(HtmlTextWriter output) {
    Text = "crash";
    using (SPWeb web = SPControl.GetContextWeb(HttpContext.Current)) {
        output.Write(SPEncode.HtmlEncode(Text)));
    }
    this.SaveProperties = true;
}


What's the answer? You can dispose any SPWeb objects obtained from a GetSubWebsForCurrentUser call for example, but don't dispose of the SPWeb associated with the current Web or you'll be in a whole world of trouble.

UPDATE: I just discovered that http://support.microsoft.com/default.aspx?scid=901259 was created sometime in the last few months in response to my original findings.

BizTalk Setup Error

Error 1928. error registering COM+ application. Contact your support personnel for more information.
or
Error 5003. Regsvcs failed for assembly c:\program files\Microsoft Biztalk Server 2004\Microsoft.Biztalk.Deployment.dll. Return code 1. (BizTalk SP1)

I ran into the above error while installing BizTalk 2004 dev/sdk components onto my windows xp/sp2 box and spent a few hours debugging the problem and managed to find a workaround. The problem stems from overly tight default permissions on keys created under HKLM\software\classes during the install. I have no clue [yet] why this happens, but the workaround is to run biztalk setup under the localsystem account rather than an administrator.

The easiest way you can do this by downloading one of the inimitable Mark Russinovich's tools called PsExec from http://www.sysinternals.com and run the following command:

c:\> psexec -s -i d:setup

where d:setup in this case presumes your biztalk install CD (or path to SP1 installer) is in drive D: the -s param means run under localsystem, and -i allows setup to interact with the desktop. Yes, the other option might be to use XP's runas command, but I don't know of any easy way of finding localsystem's password ;-)

I've only tested this by installing the development and sdk components onto a windows xp sp2 machine with visual studio 2003, since my actual biztalk server & sql db runs in a virtual server windows 2003 instance on my development box.

Initial Research

After a few hours debugging, I'd narrowed the problem down to a registry permission problem which causes the MSI execution step in question to fail badly: the step "regsvr32 XLANGByotWrap.dll" fails with 0x80070005 which we all know is "access is denied."

I used regmon and filemon (again from sysinternals) to monitor the install process -- I chose minimum install of dev/sdk via custom install -- and noticed that at some point before the regsvr32 step in question is executed, the following two important keys are created:

HKEY_LOCAL_MACHINE\SOFTWARE\ ...
Classes\XLANGWrapBYOT.XLANGWrapByot
HKEY_LOCAL_MACHINE\SOFTWARE\ ...
Classes\XLANGWrapBYOT.XLANGWrapByot.1

...and this is the killer, because this happens BEFORE the regsvr32 command is executed. The MSI gives "Administrators" read perms only (but SYSTEM gets "full control") on these regkeys, which is why the subsequent regsvr32 step fails, which tries to register the com server XLANGByotWrap.dll under these keys. You can verify this yourself by leaving the error dialog open (if you close it, the MSI will roll everything back) and dropping to the install directory and typing:
regsvr32 XLANGByotWrap.dll
You'll see that it fails with 0x80070005. Go into regedit, change the perms for Adminstrators to "Full Control" and re-run the command: Success.

I have no idea why these keys are created pre-registration, and with the incorrect perms, but it's possible to work around this issue by creating the keys with the correct perms yourself BEFORE you run setup; export the keys to xlang.reg and reimport them (after you have finished running the failed setup attempt the first time) via regedit's File|Import. The next step is change the permissions on both keys so that your own account is replaced with "administrators" and with "full control."

So, great stuff. I fire up setup myself, and lo and behold, it successfully makes it past the previous failure point only to cough up:

Error 5003. Regsvcs failed for assembly Microsoft.BizTalk.Deployment.dll. Return code 1.

Argh. So, guessing that this is more of the same malarky, I drop to a cmd prompt and try to run the command manually (while leaving the error dialog open
again) to see what the problem is:

[E:\Applications\Microsoft BizTalk Server 2004] regsvcs Microsoft.BizTalk.Deployment.dll
Microsoft (R) .NET Framework Services Installation Utility Version 1.1.4322.573
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

The following installation error occurred:
1: Failed to register assembly 'Microsoft.BizTalk.Deployment, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
2: Access to the registry key HKEY_CLASSES_ROOT\Microsoft.BizTalk.Log.LogException is denied.


Yep, it's the registry again. Bizarre. Again, the solution is to create the key yourself before you run setup. Since HKCR is a union of HKCU and HKLM, I had a look for the key under HKEY_LOCAL_MACHINE\Software\Classes where I found it. I also found a shedload of other keys, again with read-only perms for Adminstrators. I thought to myself, eh, I could just recreate the single key in question, but I figured I\'m probably going to get more than a couple of these errors, so I should export all Microsoft.Biztalk.* keys and recreate them with the proper perms before running setup again.

*** and at this point while I considered the pain of exporting a few hundred registry keys I had the idea of using PSEXEC to run the setup under the localsystem account ***

Anyway, I hope this was interesting to someone.

About the author

Irish, PowerShell MVP, .NET/ASP.NET/SharePoint Developer, Budding Architect. Developer. Montrealer. Opinionated. Montreal, Quebec.

Month List

Page List