Welcome to MSDN Blogs Sign in | Join | Help

I already wrote a post on this matter some time ago, but this week worked on the same problem on a Windows 2000 Server, of course 32 bit.

Running aspnet_regiis -i did not help so we tried to run the script Tom provides in his post, but we got the error here below:

 80070003

Line 41 is “Set objIIS = GetObject("IIS://" & strComputer & "/W3SVC/AppPools")”, this path does not exist in IIS 5 metabase, hence the error. To adapt it to IIS 5 we removed the script section that checks for Enable32BitAppOnWin64.

We run the script again and got this message:

PASS: The current value of Restrict_Run is: 0
PASS: Successfully registered mmcaspext.dll
PASS: Successfully registered AspNetMMC
Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.1433
Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.
Types registered successfully
Assembly exported to 'C:\WINNT\Microsoft.NET\Framework\v2.0.50727\AspNetMMCExt.tlb', and the type library was registered successfully
PASS: Successfully registered Assembly
Running aspmantst.exe to test the ASP.NET Tab snap-in
Attempting to create the object as CLSCTX_LOCAL_SERVER.
Create failed. hr: 80070005. QIhr: 80070005. GLE: 1008
Attempting to create the object as CLSCTX_REMOTE_SERVER to <machine_name>.
Create failed. hr: 80070005. QIhr: 80070005. GLE: 1008
Attempting to create the object as CLSCTX_INPROC_SERVER.
Object created. Attempting to call method.
Method succeded. Result: 1.1.4322.0,C:\WINNT\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll,2.0.50727.0,C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll

Code 80070005 means “Access Denied”, so we do not have enough permission to complete the configuration… The object we are trying to create, which represents the ASP.NET Ta in IIS Manager, is listed in dcomcnfg as Microsoft.Aspnet.Snapin.AspNetManagementUtility.2. In a default Windows 2000 SP4 installation, the Default Access Permission ACL is empty: when you log in as an administrator, if the ACL list is empty then the owner changes to whatever account you are logging on with: this account is the owner and implicitly has access to the COM instantiation works fine. But if the ACL list is not empty (it contains any account or group) the owner does not change at logon and the automatic mechanism just described does not work.

dcomcnfg applications custom access permission registry value permission

Likely the same missing permission we were already facing, Microsoft.Aspnet.Snapin.AspNetManagementUtility.2 did not show up in our application list… so we add a look at the same kind of permission, but this time we checked the “Default Security” tab:

dcomcnfg default security

And here we were! On another working machine this customer had the ACL list was empty, while for some reason on the failing machine the list was not empty, we had an account listed there… in such a situation there are two options:

  1. Clear the ACL list
  2. Add the Administrators group and any other account you need to explicitly grand Access Permissions to

In our case we cleared the list, run the script again (this time every step completed successfully) and the customer got his ASP.NET Tab available in IIS Manager smile_nerd

Carlo

Quote of the day:
If you develop an ear for sounds that are musical it is like developing an ego. You begin to refuse sounds that are not musical and that way cut yourself off from a good deal of experience. - John Cage

Here’s another interesting crash problem I worked on a few days ago: the application pool was randomly crashing and the following errors were logged:

Event Type:      Error
Event Source:   .NET Runtime 2.0 Error Reporting
Event Category: None
Event ID:          1000
Date:                21/08/2009
Time:                12:23:12
User:                N/A
Computer:        <computername>
Description: Faulting application w3wp.exe, version 6.0.3790.3959, stamp 45d691cc, faulting module kernel32.dll, version 5.2.3790.4062, stamp 462643a7, debug? 0, fault address 0x0000000000027d8d.

Event Type:      Warning
Event Source:   W3SVC
Event Category:           None
Event ID:          1011
Date:                21/08/2009
Time:                12:23:14
User:                N/A
Computer:        <computername>
Description: A process serving application pool <AppPoolName> suffered a fatal communication error with the World Wide Web Publishing Service. The process id was xxx. The data field contains the error number.

Even if with some difficulties (we had to disable Error Reporting as described here) we managed to capture a coupe of dumps for this crash; dumping the exception was not very helpful:

0:027> !gle
LastErrorValue: (Win32) 0x3f0 (1008) - An attempt was made to reference a token that does not exist.
LastStatusValue: (NTSTATUS) 0xc000007c - An attempt was made to reference a token that doesn't exist. This is typically done by referencing the token associated with a thread when the thread is not impersonating a client.


0:027> !printexception
There is no current managed exception on this thread


But dumping the very long stack gave some good hint at least about a potential problem (a stack overflow):

0:027> kpL
Child-SP RetAddr Call Site
00000000`05fcae90 00000642`7f895333 kernel32!RaiseException+0x73
00000000`05fcaf60 00000642`78390730 mscorwks!`string'+0x81ef3
00000000`05fcb130 00000642`780a9522 mscorlib_ni!System.OrdinalComparer.Equals(<HRESULT 0x80004001>)+0x70
00000000`05fcb170 00000642`7809822a mscorlib_ni!System.Collections.Hashtable.KeyEquals(<HRESULT 0x80004001>)+0x42
00000000`05fcb1a0 00000642`748f8976 mscorlib_ni!System.Collections.Hashtable.get_Item(<HRESULT 0x80004001>)+0x15a
00000000`05fcb260 00000642`748ff9bc System_ni!System.Collections.Specialized.NameObjectCollectionBase.FindEntry(<HRESULT 0x80004001>)+0x16
00000000`05fcb290 00000642`80580f48 System_ni!System.Collections.Specialized.NameValueCollection.Get(<HRESULT 0x80004001>)+0xc
00000000`05fcb2c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x48
00000000`05fcb300 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb340 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb380 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb3c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb400 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb440 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb480 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb4c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb500 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb540 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb580 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb5c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb600 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb640 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb680 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb6c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb700 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb740 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb780 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb7c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb800 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb840 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb880 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
00000000`05fcb8c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d
[...]

Using the err.exe utility to lookup the exit code of the process when it crashed, we can confirm we had a stack overflow:

Event Type: Warning
Event Source: W3SVC
Event Category: None
Event ID: 1009
Date: 21/08/2009
Time: 13:44:11
User: N/A
Computer: <computername>
Description: A process serving application pool <AppPoolName> terminated unexpectedly.
The process id was '5392'. The process exit code was '0x800703e9'.






C:\>err 0x800703e9
# for hex 0x800703e9 / decimal -2147023895
COR_E_STACKOVERFLOW corerror.h
# Is raised by the EE when the execution stack overflows as
# it is attempting to ex
# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x3e9
# for hex 0x3e9 / decimal 1001
ERROR_STACK_OVERFLOW winerror.h
# Recursion too deep; the stack overflowed.
# 2 matches found for "0x800703e9"


In the IIS log the request that lead to the crash was like this:

GET

/MyApp/test.aspx?currentPreferences=2&ParentId=1&ClientDateTime=Wed%20Aug%2019%202009%2009:09:57%20GMT+0100%20(GMT%20Standard%20Time)&TimeZone=-60&Language=undefined&Currency=undefined&OrgUnitId=undefined

Basically some user was using a robot to scrape the web site and the Language parameter (along with a few others) was not correctly set; in this case the customer’s code was not properly validating those parameters (using a browser they are always valid) and this cause the endless recursion that ultimately exhausted the stack.

Needless to say, improving the parameter validation logic resolved the problem smile_nerd

 

Carlo

Quote of the day:
Seeing ourselves as others see us would probably confirm our worst suspicions about them. - Franklin P. Adams

Yesterday my Italian colleagues in Developer Support and I officially inaugurated our new team blog: if you can read Italian then join us at http://blogs.msdn.com/itasupport smile_nerd

 

Carlo

Quote of the day:
Everything that irritates us about others can lead us to an understanding of ourselves. - Carl Jung

If you have a complex solution, with a lot of folders and subfolders, and you are hosting and debugging it on a remote IIS server (not on your local machine), you may get an error similar to the following:

An error occurred loading a configuration file: Failed to start monitoring changes to '<path>' because the network BIOS command limit has been reached. For more information on this error, please refer to Microsoft knowledge base article 810886. Hosting on a UNC share is not supported for the Windows XP Platform

The article mentioned in the error message (810886) suggests to change the MaxCmds and MaxMpxCt values, but when I had the chance to work on this problem this solution does not always work (anyway I suggest you to give it a try before discarding it).

You may find another message in your event log, like the following:

Event Type: Warning
Event Source: Srv
Event Category: None
Event ID: 2021
Date:
Time:
User: N/A
Computer:
Description: The server was unable to allocate a work item x times in the last 60 seconds

If you do, give the article 317249 a try (increase the MaxWorkItems value).

The solution I find most useful is the one described in 911272: if your .NET build is at least 2.0.50727.62 you already have the fix mentioned in the article but you may need to activate it:

Registry information
To enable this hotfix, you must add the following DWORD value at the following registry key:
HKLM\Software\Microsoft\ASP.NET\FCNMode
The following table lists possible values for the FCNMode DWORD value and the behavior that is associated with each value.

Value Behavior
Does not exist This is the default behavior. For each subdirectory, the application will create an object that will monitor the subdirectory
0 or greater than 2 This is the default behavior. For each subdirectory, the application will create an object that will monitor the subdirectory
1 The application will disable File Change Notifications (FCNs)
2 The application will create one object to monitor the main directory. The application will use this object to monitor each subdirectory

I suggest to set FCNMode to 2, so you’ll still have File Change Notifications in place.

 

Carlo

Quote of the day:
The greatest challenge to any thinker is stating the problem in a way that will allow a solution. - Bertrand Russell

I’m back after the summer break (3 weeks spent trying to master the “Do It Yourself” art at home smile_regular) and my second day in office I got an interesting problem with remote debugging: after installing the Service Pack 2 for .NET 2.0, when trying to debug our web application (hosted on a remote IIS) we were getting the following error: “Unable to start debugging on the web server. An authentication error occurred while communicating with the web server”. Note, you can get the same error if you install the Service Pack 1 for .NET 3.5: the reason is simple, if you install the SP1 for .NET 3.5 you’ll automatically get the SP2 for .NET 2.0. Another point: you are using host headers in your site.

Anyway, the error is caused by a security change: in .NET 3.5 SP1 (and .NET 2.0 SP2) now defaults to specifying the host name used in the request URL in an SPN in the NTLM authentication package. The NTLM authentication process includes a challenge issued by the destination machine and sent back to the client machine. When Windows receives a challenge it generated itself, authentication will fail unless the connection is a loop back connection. When a Web Site is configured with a host header, the host name is neither the machine name nor the loop back IP address nor the machine's IP address, so the authentication request will fail.

There are two possible solutions:

  1. The recommended approach is to map your host header name to the loop back address in the registry. Here are the steps:
    • Click Start > Run, type regedit and click OK
    • In Registry Editor, select the registry key “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0”
    • Right-click MSV1_0 > New > Multi-String Value
    • Type “BackConnectionHostNames” and press ENTER
    • Right-click “BackConnectionHostNames” > Modify
    • In the Value data box, type the host name or the host names for the sites that are on the local computer, then click OK
    • Quit the Registry Editor and reset IIS
  2. A less secure work around is to disable the loop back check, as described in http://support.microsoft.com/kb/896861

If you want more information on this matter you have have a look at http://blogs.msdn.com/lukaszp/archive/2008/07/18/reporting-services-http-401-unauthorized-host-headers-require-your-attention.aspx.

Carlo

Quote of the day:
If fifty million people say a foolish thing, it is still a foolish thing. - Anatole France

My colleague Feliciano has just made me aware of an extraordinary security bulletin we have just released for a new vulnerability discovered in ATL libraries which could allow remote code execution; here are the information I am aware of so far:

The updates to install:

 

Carlo

Quote of the day:
Those who dream by day are cognizant of many things which escape those who dream only by night. - Edgar Allan Poe

If you search the Internet you’ll likely find a good number of articles and blog posts about how to configure ASP.NET 1.1 on IIS 7, here are a couple of good examples:

Something I have not found written elsewhere is why it is not possible configure ASP.NET properties from the IIS Manager interface? Even if you correctly configure the application pool (32 bit, Classic pipeline), use the workaround to avoid the error on applicationHost.config, add the IgnoreSectionHandler to avoid ASP.NET 1.1 runtime exceptions due to the not recognized IIS 7 configuration tags and finally the ASP.NET 1.1 pages works fine and are served correctly, you’ll not have the “ASP.NET” icon group in IIS Manager:

Missing "ASP.NET" group

As you can imagine, if you move the application to an application pool where you are running ASP.NET 2.0, the icon group appears where you expect it to be:

 With "ASP.NET" group

Well, it turns out that ASP.NET 1.1 configuration is not supported by InetMgr.exe (the IIS Manager), you have to use appcmd.exe using /commit:machine (for machine.config) or /commit:webroot (for the root web.config) to check if the changes work and they end up where they are supposed to. Note, there are some limitations because of the lack of a complete schema; if you feel brave enough you can create your own custom schema, I do not think (this is my opinion, I do not have an official work on this) that Microsoft will provide such schema. Or if you are even braver you can edit the .config files directly in Notepad, but this sounds like business for real geeks… how much geek do you feel? smile_nerd

 

Carlo

Quote of the day:
The belief in a supernatural source of evil is not necessary; men alone are quite capable of every wickedness. - Joseph Conrad

Every now and then we got a call for an application which, randomly and without a specific pattern or apparent reason, shuts down all user’s sessions. Since ASP.NET 2.0 we can use Web Events to have more information on what is happening at the runtime level and this time the message we had in the event log was pretty clear:

Event code: 1002
Event message: Application is shutting down. Reason: Configuration changed.
Event time: 
Event time (UTC):
Event ID: 
Event sequence:
Event occurrence: 1
Event detail code: 

Application information:
Application domain: /LM/W3SVC/1045621189/Root-2-1742334186915428
Trust level: Full
Application Virtual Path: /
Application Path: C:\Inetpub\wwwroot\
Machine name: <machinename>

Process information:
Process ID: 1234
Process name: w3wp.exe
Account name: NT AUTHORITY\NETWORK SERVICE

We used Process Monitor to track access to the relevant .config files which are usually the cause for this kind of problem, but with no luck.

To make a long story short, we had a look at the events around the time when the session was lost and we noticed it usually followed some exception tracking logic the customer had used, so we had a look at the source code and found something interesting: the customer had some code to write and maintain a custom log on a text file and this work was done on a background thread. This code was using the ConfigurationManager class to read some settings from the web.config.

Now the interesting part: the background thread was executed in a different AppDomain than the ASP.NET application and it needed to initialize this new AppDomain to use the ConfigurationManager; as part of this initialization we create a new File Change Notification object to monitor machine.config and web.config files for changes. When the background thread exited after his job was done, the File Change Notification object encountered this error:

0x800703E3 ( -2147023901 ) = ERROR_OPERATION_ABORTED
The I/O operation has been aborted because of either a thread exit or an application request

Note, that is not an exception; but this change notification event was “head” by all ASP.NET applications which is the expected behavior, and all AppDomains were restarted: the end users were therefore redirected to the login page smile_nerd.

How do you avoid this situation? Well, we made a small change to the exception handling code to not use ConfigurationManager in the background thread.

 

Carlo

Quote of the day:
When a person can no longer laugh at himself, it is time for others to laugh at him. - Thomas Szasz

I have already wrote here about a StackOverflowException I recently came across; after a while I got another quite similar problem, still a StackOverflowException with a very long recursion.

Thread 36 is the one where the exception was thrown:

0:000> !threads
ThreadCount: 21
UnstartedThread: 0
BackgroundThread: 21
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
17 1 950 000f2580 1808220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
27 2 1bfc 00100018 b220 Enabled 00000000:00000000 000eed48 0 MTA (Finalizer)
28 3 300 00117068 80a220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Completion Port)
29 4 1cf4 0011a458 1220 Enabled 00000000:00000000 000eed48 0 Ukn
9 5 ec0 001702e0 220 Enabled 00000000:00000000 000eed48 0 Ukn
31 6 2414 00171f68 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
32 7 1f24 00172338 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
33 8 97c 001729e0 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
34 9 13bc 00173088 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
35 a 22f8 00173a50 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
36 b 1e60 00174540 180b220 Disabled 12445a64:124475b8 0011ab48 1 MTA (Threadpool Worker) System.StackOverflowException (1a0a00a4)
37 c 1c8c 00174cf8 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
15 d 1934 0017d040 880a220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Completion Port)
7 e 2028 0017ece8 220 Enabled 00000000:00000000 000eed48 0 Ukn
8 f dbc 0016f280 220 Enabled 00000000:00000000 000eed48 0 Ukn
4 10 2298 05007008 220 Enabled 00000000:00000000 000eed48 0 Ukn
6 11 20c0 05004278 220 Enabled 00000000:00000000 000eed48 0 Ukn
3 12 c9c 05003b70 220 Enabled 00000000:00000000 000eed48 0 Ukn
5 13 1a84 04ff7a60 220 Enabled 00000000:00000000 000eed48 0 Ukn
2 14 253c 0d378ee0 220 Enabled 00000000:00000000 000eed48 0 Ukn
42 15 1760 0d38b3d8 220 Enabled 00000000:00000000 000eed48 0 Ukn

Again, here is the managed stack of the thread:

0:036> !clrstack
OS Thread Id: 0x1e60 (36)
ESP EIP
04e94acc 77e42004 [FaultingExceptionFrame: 04e94acc]
04e95058 77e42004 [HelperMethodFrame: 04e95058]
04e950c4 65230cc1 System.Data.RBTree`1+TreePage[[System.__Canon, mscorlib]]..ctor(Int32)
04e950d4 65230abe System.Data.RBTree`1[[System.__Canon, mscorlib]].AllocPage(Int32)
04e950f8 652309fc System.Data.RBTree`1[[System.__Canon, mscorlib]].InitTree()
04e95108 65230961 System.Data.DataRowCollection..ctor(System.Data.DataTable)
04e95118 652307c2 System.Data.DataTable..ctor()
04e95134 65230535 System.Data.Common.DataTableMapping.GetDataTableBySchemaAction(System.Data.DataSet, System.Data.MissingSchemaAction)
04e95150 6523037c System.Data.ProviderBase.SchemaMapping..ctor(System.Data.Common.DataAdapter, System.Data.DataSet, System.Data.DataTable, System.Data.ProviderBase.DataReaderContainer, Boolean, System.Data.SchemaType, System.String, Boolean, System.Data.DataColumn, System.Object)
04e9519c 6522fbac System.Data.Common.DataAdapter.FillMappingInternal(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, System.Data.DataColumn, System.Object)
04e951d0 6522fc1e System.Data.Common.DataAdapter.FillMapping(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, System.Data.DataColumn, System.Object)
04e95218 6522f9e6 System.Data.Common.DataAdapter.FillFromReader(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, Int32, System.Data.DataColumn, System.Object)
04e95270 6522f942 System.Data.Common.DataAdapter.Fill(System.Data.DataSet, System.String, System.Data.IDataReader, Int32, Int32)
04e952b4 65230105 System.Data.Common.DbDataAdapter.FillInternal(System.Data.DataSet, System.Data.DataTable[], Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
04e9530c 65230010 System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
04e95350 6559401d System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, System.String)
04e95384 6678d11f System.Web.UI.WebControls.SqlDataSourceView.ExecuteSelect(System.Web.UI.DataSourceSelectArguments)
04e95424 6668f498 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04e95434 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04e9544c 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04e95458 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04e9545c 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04e95488 668ecdcd System.Web.UI.WebControls.BaseDataBoundControl.set_RequiresDataBinding(Boolean)
04e95498 667da23b System.Web.UI.WebControls.GridView.set_PageIndex(Int32)
04e954a8 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)
04e959a8 667928ce System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(System.EventArgs)
04e959bc 66792b45 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(System.Collections.IEnumerable)
04e959cc 6668f4a4 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04e959dc 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04e959f4 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04e95a00 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04e95a04 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04e95a30 668ecdcd System.Web.UI.WebControls.BaseDataBoundControl.set_RequiresDataBinding(Boolean)
04e95a40 667da23b System.Web.UI.WebControls.GridView.set_PageIndex(Int32)
04e95a50 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)
04e95f50 667928ce System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(System.EventArgs)
04e95f64 66792b45 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(System.Collections.IEnumerable)
04e95f74 6668f4a4 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04e95f84 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04e95f9c 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04e95fa8 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04e95fac 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04e95fd8 668ecdcd System.Web.UI.WebControls.BaseDataBoundControl.set_RequiresDataBinding(Boolean)
04e95fe8 667da23b System.Web.UI.WebControls.GridView.set_PageIndex(Int32)
04e95ff8 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)

[...]
04ebea70 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)
04ebef70 667928ce System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(System.EventArgs)
04ebef84 66792b45 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(System.Collections.IEnumerable)
04ebef94 6668f4a4 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04ebefa4 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04ebefbc 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04ebefc8 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04ebefcc 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04ebeff8 660e1a57 System.Web.UI.WebControls.BaseDataBoundControl.OnPreRender(System.EventArgs)
04ebf008 667e07da System.Web.UI.WebControls.GridView.OnPreRender(System.EventArgs)
04ebf030 660abc21 System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf048 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf060 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf078 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf090 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf0a8 660a7c4b System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
04ebf200 660a77a4 System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
04ebf238 660a76d1 System.Web.UI.Page.ProcessRequest()
04ebf270 660a7666 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext)
04ebf27c 660a7642 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)
04ebf290 0ad37afe ASP.search_aspx.ProcessRequest(System.Web.HttpContext)
04ebf2a0 660adb16 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
04ebf2d4 6608132c System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
04ebf314 6608c5c3 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception)
04ebf364 660808ac System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object)
04ebf380 66083e1c System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest)
04ebf3b4 66083ac3 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest)
04ebf3c4 66082c5c System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)
04ebf5d8 79f68cde [ContextTransitionFrame: 04ebf5d8]
04ebf60c 79f68cde [GCFrame: 04ebf60c]
04ebf768 79f68cde [ComMethodFrame: 04ebf768]

After the DataBound event hander is executed, we always call set_PageIndex and go through the binding logic over and over. What does it mean?

Well, either use Reflector or download the .NET Framework source (or the SSCLI, Shared Source Common Language Infrastructure), if you have a look at the implementation of set_PageIndex you’ll see something like this:

public virtual void set_PageIndex(int value)
{
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
if (this.PageIndex != value)
{
this._pageIndex = value;
if (base.Initialized)
{
base.RequiresDataBinding = true;
}
}
}

Going deeper we see this:

protected bool RequiresDataBinding()
{
get
{
return this._requiresDataBinding;
}
set
{
if (((value && this._preRendered) && ((this.DataSourceID.Length > 0) && (this.Page != null))) && !this.Page.IsCallback)
{
this._requiresDataBinding = true;
this.EnsureDataBound();
}
else
{
this._requiresDataBinding = value;
}
}
}






protected virtual void EnsureDataBound()
{
try
{
this._throwOnDataPropertyChange = true;
if (this.RequiresDataBinding && ((this.DataSourceID.Length > 0) || this._requiresBindToNull))
{
this.DataBind();
this._requiresBindToNull = false;
}
}
finally
{
this._throwOnDataPropertyChange = false;
}
}

Here is the source code of the faulting page:

Sub Gridview1_DataBound(ByVal sender As Object, ByVal e As EventArgs)
Try
If GridView1.Rows.Count > 0 Then
Dim pagerRow As GridViewRow = GridView1.BottomPagerRow

[...]

Dim CurrentPage As String

If Request.QueryString("page") <> "" Then
CurrentPage = Request.QueryString("page")
Else
CurrentPage = 1
End If

Try
GridView1.PageIndex = CurrentPage - 1
Catch
CurrentPage = 1
GridView1.PageIndex = CurrentPage - 1
End Try

[...]

End Try
End Sub

So, if we change the PageIndex value, under some circumstances we call the DataBind method, the OnDataBound event is fired, the DataBound event hander is executed, PageIndex is changed again and so on until the stack is exhausted.

Bottom line here is: do not change the PageIndex value inside the DataBound event handler!

DataSource or DataSourceID?

One of the conditions to implicitly call DataBind() is to have a value set for DataSourceID:

protected bool RequiresDataBinding()
{
get
{
return this._requiresDataBinding;
}
set
{
if (((value && this._preRendered) && ((this.DataSourceID.Length > 0) && (this.Page != null))) && !this.Page.IsCallback)
{
this._requiresDataBinding = true;
this.EnsureDataBound();
}
else
{
this._requiresDataBinding = value;
}
}
}

Honestly I have not tried it (I’ll do and update the post if needed), but I think if we use DataSource rather than DataSourceID we’ll not incur in this problem.

Carlo

Quote of the day:
There is nothing more dreadful than imagination without taste. - Johann Wolfgang von Goethe

I recently came across an odd problem the customer got on his SharePoint server: when the clients had the Office Live add-on installed they were constantly refused with a 403 error. The problem is well described here.

If you have this problem, there is a fix for you: 970946.

If you do not want to install the fix, you might consider to filter the UserAgent string you receive on the server (well, you should filter it before the web request is processed on the server) as one of my customers is testing: if the UserAgent string contains the word “Mozilla” and “Office”* or “non-browser” or “FrontPage”*, just remove the unwanted token.

 

Carlo

Quote of the day:
All things are difficult before they are easy. - Thomas Fuller

A few days ago I was working on a repro I got from a customer as I very often do, and for some reason after a while my IIS started to behave oddly, pages where not served, the application pool was stuck doing “something” and whenever I tried to open the IIS Manager I got the error “There was an error when trying to connect. Do you want to retype your credentials and try again? Cannot create a file when that file already exists”:

 Failed to connect

Needless to say that being IIS on my local machine and I have not made any changes to the security/ACLs/DCOM etc… there should be no need to retype my credentials; and by the way, even retyping them did not help.

By the way, if I tried to remotely connect to another machine of mine, I got the message “The type initializer for ‘Microsoft.Web.Management.Remoting.HttpChannel’ threw an exception”:

Type initializer throw an exception 

My next step has been to try to restart the World Wide Web Publishing Service: it was (oddly?) stopped, but again I got an error “Windows could not start the World Wide Web Publishing Service service on Local Computer. Error 1068: The dependency service or group failed to start”:

The dependency service or group failed to start

The W3SVC service has a dependency on WAS (Windows Process Activation Service), I tried to start it manually and got “Windows could not start the Windows Process Activation Service service on Local Computer. Error 183: Cannot create a file when that file already exists.”:

Could not start WAS service

That is the same message I got from IIS Manager, so I thought to have a look at the event log to find out more: I was wrong! I got “MMC could not create the snap-in. The snap-in might not have been installed correctly”:

 MMC could not create the snap-in

I quickly found out that virtually every MMC snap-in was broken on my machine (“Server Manager” “Certificates”, “Local Users and Groups”, just name one) but why?!?  smile_omg

Well… on Windows 2008, MMC is based on .NET as of course is IIS and when the problem first appeared I was tampering my machine.config file to try different ThreadPool settings… smile_thinking

The golden rule in computing reads “Always back-up sensitive data!”… after restoring my clean machine.config all the problems above went away! smile_nerd

For curiosity I had a deeper look at it and found the following lines:

<system.web>

<processModel autoConfig="true"/>

<processModel autoConfig="false" minWorkerThreads="100"
minIoThreads="100" maxWorkerThreads="404" maxIoThreads="404"/>

<httpRuntime minFreeThreads="152" minLocalRequestFreeThreads="152"/>

[...]

Easy to spot it now, eh? For my repro I had set autoConfig=”false” but then I decided to set it to “true”, for some reason I added a new <processModel> element with its own autoConfig=”true” and forgot to remove the “old” <processModel>… At least I learnt something new from my foolishness! smile_embaressed

Note: there might be other reasons if you get the errors above, but always keep a clean backup of your configuration files at hand, just in case…

 

 

Carlo

Quote of the day:
We are continually faced with a series of great opportunities brilliantly disguised as insoluble problems. - John W. Gardner

The .shell command in Windbg allows to pipe the output of a debugger command to an external process and automatically print its output back inside the debugger window; a useful example is the command FIND, for example if we want to parse the stack for every thread and find every call where the word “isapi” is involved:

0:036> .shell -ci "~*kpL1000" find /i "isapi"
013cff78 1004f94e ISAPI_Rewrite!TerminateFilter+0x3cef
013cffb0 1004f9f3 ISAPI_Rewrite!TerminateFilter+0x4462e
013cffec 00000000 ISAPI_Rewrite!TerminateFilter+0x446d3
0144ff78 1004f94e ISAPI_Rewrite+0x7763
0144ffb0 1004f9f3 ISAPI_Rewrite!TerminateFilter+0x4462e
0144ffec 00000000 ISAPI_Rewrite!TerminateFilter+0x446d3
.shell: Process exited

Incidentally also LogParser (one of my favorite debugging tools) can accept data to be parsed from the input stream using the STDIN keyword, so for example refactoring a script I posted some time ago we can find out if there are any duplicated assemblies in our application pool that should be moved to the GAC:

0:000> .shell -ci "!peb" logparser "select extract_filename(text) as Duplicated_Assemblies, count(Duplicated_Assemblies) as Hits from STDIN where index_of(text, 'temporary asp.net files') > 0 group by Duplicated_Assemblies having count(Duplicated_Assemblies) > 1" -i:textline -o:nat -rtp:-1
Duplicated_Assemblies Hits
---------------------------- ----
errormanager.dll 2
winformsui.dll 2
externallibraryinterface.dll 2
ptshopengine.dll 2
schemas.dll 2
dbengine.dll 2
flowservice.dll 2

Statistics:
-----------
Elements processed: 182
Elements output: 7
Execution time: 0.02 seconds

.shell: Process exited

 

Following the same principle, we can find out if there are strong named assemblies in our /bin folder as follows:

0:000> .shell -ci "!dumpdomain" find /i "shared domain"
Shared Domain: 0x793f2aa8
.shell: Process exited




0:000> .shell -ci "!dumpdomain 0x793f2aa8" logparser "SELECT DISTINCT EXTRACT_FILENAME(text) as Strong_Named_Assemblies_In_/bin FROM STDIN WHERE INDEX_OF(to_lowercase(text), 'temporary asp.net files') > 0" -i:TEXTLINE -o:NAT -RTP:-1
Strong_Named_Assemblies_In_/bin
-----------------------------------------
crypto.dll
radplaceholder.dll
scms.dll
sqldac.dll
scontrollibrary.dll
spell.dll
editor.dll
scms.resources.dll

Statistics:
-----------
Elements processed: 164
Elements output: 8
Execution time: 0.01 seconds

.shell: Process exited

 

Instead of typing the whole command you can save it in a text file and execute it directly within Windbg with a command like “$><c:\debuggers\snassemblies.txt”.

 

Carlo

Quote of the day:
Setting a good example for children takes all the fun out of middle age. - William Feather

The application pool for this site was getting disabled quite frequently and we found quite a few entries like the following in the event log:

Event Type: Error
Event Source: W3SVC
Event Category: None
Event ID: 1002
Date: 19/11/2008
Time: 15:20:23
User: N/A
Computer: <computername>
Description: Application pool 'DefaultAppPool' is being automatically disabled due to a series of failures in the process(es) serving that application pool

In this case the customer already had some debugging skills so when he called CSS he already had a few dumps available to analyze; they were some process shutdown dumps (taken on Kernel32!TerminateProcess), strangely we had no second chance dumps (maybe because of one of these reasons?) but they’ve been a good point to start from anyway.

First, let’s have a look at the exceptions:

0:000> !dumpheap -type Exception -stat 

[...]

Statistics:
MT Count TotalSize Class Name
79333ed4 1 12 System.Text.DecoderExceptionFallback
79333e90 1 12 System.Text.EncoderExceptionFallback
79330d44 1 72 System.ExecutionEngineException
79330cb4 1 72 System.StackOverflowException
79330c24 1 72 System.OutOfMemoryException
7931ffd4 1 72 System.NullReferenceException
6610c7fc 1 84 System.Web.HttpUnhandledException
79330dd4 2 144 System.Threading.ThreadAbortException
79318afc 2 144 System.InvalidOperationException
7931740c 5 160 System.UnhandledExceptionEventHandler
Total 16 objects

Remember, a few special exceptions are loaded when the AppDomain is first created (see here) so let’s try to see if there is still something significant on the threads:

0:000> !threads
ThreadCount: 21
UnstartedThread: 0
BackgroundThread: 21
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
17 1 950 000f2580 1808220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
27 2 1bfc 00100018 b220 Enabled 00000000:00000000 000eed48 0 MTA (Finalizer)
28 3 300 00117068 80a220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Completion Port)
29 4 1cf4 0011a458 1220 Enabled 00000000:00000000 000eed48 0 Ukn
9 5 ec0 001702e0 220 Enabled 00000000:00000000 000eed48 0 Ukn
31 6 2414 00171f68 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
32 7 1f24 00172338 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
33 8 97c 001729e0 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
34 9 13bc 00173088 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
35 a 22f8 00173a50 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
36 b 1e60 00174540 180b220 Disabled 12445a64:124475b8 0011ab48 1 MTA (Threadpool Worker) System.StackOverflowException (1a0a00a4)
37 c 1c8c 00174cf8 180b220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Worker)
15 d 1934 0017d040 880a220 Enabled 00000000:00000000 000eed48 0 MTA (Threadpool Completion Port)
7 e 2028 0017ece8 220 Enabled 00000000:00000000 000eed48 0 Ukn
8 f dbc 0016f280 220 Enabled 00000000:00000000 000eed48 0 Ukn
4 10 2298 05007008 220 Enabled 00000000:00000000 000eed48 0 Ukn
6 11 20c0 05004278 220 Enabled 00000000:00000000 000eed48 0 Ukn
3 12 c9c 05003b70 220 Enabled 00000000:00000000 000eed48 0 Ukn
5 13 1a84 04ff7a60 220 Enabled 00000000:00000000 000eed48 0 Ukn
2 14 253c 0d378ee0 220 Enabled 00000000:00000000 000eed48 0 Ukn
42 15 1760 0d38b3d8 220 Enabled 00000000:00000000 000eed48 0 Ukn

Dumping the managed stack for thread 36, the recursion is quite obvious:

0:036> !clrstack
OS Thread Id: 0x1e60 (36)
ESP EIP
04e94acc 77e42004 [FaultingExceptionFrame: 04e94acc]
04e95058 77e42004 [HelperMethodFrame: 04e95058]
04e950c4 65230cc1 System.Data.RBTree`1+TreePage[[System.__Canon, mscorlib]]..ctor(Int32)
04e950d4 65230abe System.Data.RBTree`1[[System.__Canon, mscorlib]].AllocPage(Int32)
04e950f8 652309fc System.Data.RBTree`1[[System.__Canon, mscorlib]].InitTree()
04e95108 65230961 System.Data.DataRowCollection..ctor(System.Data.DataTable)
04e95118 652307c2 System.Data.DataTable..ctor()
04e95134 65230535 System.Data.Common.DataTableMapping.GetDataTableBySchemaAction(System.Data.DataSet, System.Data.MissingSchemaAction)
04e95150 6523037c System.Data.ProviderBase.SchemaMapping..ctor(System.Data.Common.DataAdapter, System.Data.DataSet, System.Data.DataTable, System.Data.ProviderBase.DataReaderContainer, Boolean, System.Data.SchemaType, System.String, Boolean, System.Data.DataColumn, System.Object)
04e9519c 6522fbac System.Data.Common.DataAdapter.FillMappingInternal(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, System.Data.DataColumn, System.Object)
04e951d0 6522fc1e System.Data.Common.DataAdapter.FillMapping(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, System.Data.DataColumn, System.Object)
04e95218 6522f9e6 System.Data.Common.DataAdapter.FillFromReader(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, Int32, System.Data.DataColumn, System.Object)
04e95270 6522f942 System.Data.Common.DataAdapter.Fill(System.Data.DataSet, System.String, System.Data.IDataReader, Int32, Int32)
04e952b4 65230105 System.Data.Common.DbDataAdapter.FillInternal(System.Data.DataSet, System.Data.DataTable[], Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
04e9530c 65230010 System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
04e95350 6559401d System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, System.String)
04e95384 6678d11f System.Web.UI.WebControls.SqlDataSourceView.ExecuteSelect(System.Web.UI.DataSourceSelectArguments)
04e95424 6668f498 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04e95434 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04e9544c 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04e95458 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04e9545c 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04e95488 668ecdcd System.Web.UI.WebControls.BaseDataBoundControl.set_RequiresDataBinding(Boolean)
04e95498 667da23b System.Web.UI.WebControls.GridView.set_PageIndex(Int32)
04e954a8 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)
04e959a8 667928ce System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(System.EventArgs)
04e959bc 66792b45 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(System.Collections.IEnumerable)
04e959cc 6668f4a4 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04e959dc 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04e959f4 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04e95a00 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04e95a04 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04e95a30 668ecdcd System.Web.UI.WebControls.BaseDataBoundControl.set_RequiresDataBinding(Boolean)
04e95a40 667da23b System.Web.UI.WebControls.GridView.set_PageIndex(Int32)

04e95a50 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)
04e95f50 667928ce System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(System.EventArgs)
04e95f64 66792b45 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(System.Collections.IEnumerable)
04e95f74 6668f4a4 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04e95f84 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04e95f9c 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04e95fa8 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04e95fac 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04e95fd8 668ecdcd System.Web.UI.WebControls.BaseDataBoundControl.set_RequiresDataBinding(Boolean)
04e95fe8 667da23b System.Web.UI.WebControls.GridView.set_PageIndex(Int32)
04e95ff8 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)

[...]
04ebea70 0ad3e096 ASP.search_aspx.Gridview1_DataBound(System.Object, System.EventArgs)
04ebef70 667928ce System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(System.EventArgs)
04ebef84 66792b45 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(System.Collections.IEnumerable)
04ebef94 6668f4a4 System.Web.UI.DataSourceView.Select(System.Web.UI.DataSourceSelectArguments, System.Web.UI.DataSourceViewSelectCallback)
04ebefa4 66792c0f System.Web.UI.WebControls.DataBoundControl.PerformSelect()
04ebefbc 6679285e System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
04ebefc8 667dcf35 System.Web.UI.WebControls.GridView.DataBind()
04ebefcc 660e1ac3 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
04ebeff8 660e1a57 System.Web.UI.WebControls.BaseDataBoundControl.OnPreRender(System.EventArgs)
04ebf008 667e07da System.Web.UI.WebControls.GridView.OnPreRender(System.EventArgs)
04ebf030 660abc21 System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf048 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf060 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf078 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf090 660abc7c System.Web.UI.Control.PreRenderRecursiveInternal()
04ebf0a8 660a7c4b System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
04ebf200 660a77a4 System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
04ebf238 660a76d1 System.Web.UI.Page.ProcessRequest()
04ebf270 660a7666 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext)
04ebf27c 660a7642 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)
04ebf290 0ad37afe ASP.search_aspx.ProcessRequest(System.Web.HttpContext)
04ebf2a0 660adb16 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
04ebf2d4 6608132c System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
04ebf314 6608c5c3 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception)
04ebf364 660808ac System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object)
04ebf380 66083e1c System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest)
04ebf3b4 66083ac3 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest)
04ebf3c4 66082c5c System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)
04ebf5d8 79f68cde [ContextTransitionFrame: 04ebf5d8]
04ebf60c 79f68cde [GCFrame: 04ebf60c]
04ebf768 79f68cde [ComMethodFrame: 04ebf768]

 

The next step is to find out why the OnDataBound event is firing over and over; here is the source code for the faulting page (simplified to show only the relevant bits):

Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs)

Dim cmd As String = "select * from products"

If Not IsPostBack Then

' when there is a blank search, display all products
If SearchString = "" Then

SqlDataSource1.SelectCommand = cmd
GridView1.DataBind()

Else
' when there are keywords (not a blank search)

' some logic to change the sql query
GridView1.DataBind()

If GridView1.Rows.Count < 3 Then ' displays suggestions if results are less then 3
For i = 0 To Keywords.Count - 1
' some logic to change the sql query
GridView1.DataBind()
Next

For i = 0 To FoundNewKeywords.Count - 1
For s = 0 To Keywords.Count - 1
' some logic to change the sql query
GridView1.DataBind()
Next

For j = i To FoundNewKeywords.Count - 1
' some logic to change the sql query
GridView1.DataBind()

If j = FoundNewKeywords.Count - 1 And FoundNewKeywords.Count > 2 Then
For m = j - 1 To 1 Step -1
' some logic to change the sql query
GridView1.DataBind()
Next

If i < 1 Then
For m = 2 To j - 1
' some logic to change the sql query
GridView1.DataBind()
Next
End If
End If
Next
Next
End If
End If
End If
End Sub




Sub Gridview1_DataBound(ByVal sender As Object, ByVal e As EventArgs)
' Some custom logic here
End Sub


 

From a high level perspective the intention was to start with a “return everything” query and refine it step by step taking into account keywords specified by the user and add logic to suggest other records that might interest the user. From an operation standpoint calling DataBind() multiple times means the whole data binding logic is executed over and over, such as the custom DataBound event handler: that way, depending on what we’re doing, we could exhaust the stack space which is what was happening in this case.

The solution is simple: there is no need to call DataBind() many times, just call it once after we have refined our query.

 

 

Carlo

Quote of the day:
To avoid situations in which you might make mistakes may be the biggest mistake of all. - Peter McWilliams

Have you ever found yourself patiently waiting for a problem to reproduce with your debugger ready, and when it happens you just find there are no signs of your dump anywhere? If you are using adplus you likely had the text logs, but nothing more…

In such situations it is possible that the OS is terminating the process before the dump is fully written. If you are tying to dump an IIS process and you want to save some time and headaches, try this small cunning: temporarily disable the “Enable pinging” and “Enable rapid-fail protection” flags in the Health tab for your application pool:

Health tab

Sometimes can be useful to tell IIS to not kill a failing worker process but rather leave it orphaned:

Features of Worker Process Isolation Mode

Orphaning Worker Processes

You can configure worker process isolation mode to orphan a worker process that the WWW service deems to be failing. The WWW service usually terminates a failing worker process and replaces it. If you enable orphaning, the WWW service allows a failing worker process to continue running, but separates it from the application pool (making it an orphan) and starts a new worker process in its place. You can configure the WWW service to run a command on the orphaned worker process — for example, launching a debugger.

For more information about orphaning worker processes, including how to configure this feature, see Running IIS 6.0 as an Application Server in this book and OrphanWorkerProcess Metabase Property metabase property.

In IIS 6 there the following three metabase properties can be handy to run some custom actions in case of an application pool failure:

  • OrphanWorkerProcess: The OrphanWorkerProcess property, when set to true, notifies the World Wide Web Publishing Service (WWW Service) not to terminate a worker process that fails to respond to pings, but to instead orphan the worker process in the application pool if the worker process suffers fatal errors
  • OrphanActionParams: The OrphanActionParams property specifies command-line parameters for the executable specified by the OrphanActionExe Metabase Property. To specify the process ID of the orphaned process, use %1%.
  • OrphanActionExe: The OrphanActionExe property specifies an executable to run when the World Wide Web Publishing Service (WWW service) orphans a worker process. You can use the OrphanActionParams Metabase Property to send parameters to the executable

The article How to generate a dump file when ASP.NET deadlocks in IIS 6.0 explains how to use the properties above and despite its title, you can use this technique to run the custom actions you need/want not only in case of an ASP.NET deadlock but in every circumstance that fits your needs.

In IIS 7 you can easily use the Advanced Settings dialog or your application pool:

Advanced Settings in IIS 7

Finally, while w3wp.exe cannot run without Data Execution Prevention, if you are debugging a custom process you may want to add it to the exclusion list:

Data Execution Prevention

 

 

Carlo

Quote of the day:
If the only tool you have is a hammer, you tend to see every problem as a nail. - Abraham Maslow

I wrote about why GDI+ is not supported in a service a couple of years ago but this is still a debated topic (or I should better say a misunderstood topic), then WPF (Windows Presentation Foundation) came into the game and it brought some more uncertainties with it.

Recently I worked on a custom application which basically was meant to made of a Windows Form client and a WCF Web Service used to get some data from a database, create a 3D image (a sort of chart) and send it to the client as a jpg image; the graphic part was done using classes such as Viewport3D, PerspectiveCamera, ModelVisual3D, RenderTargetBitmap and others taken from the System.Windows.Media.*  and System.Drawing namespaces.

Everything was working fine as long as the project was being developed and debugged against the ASP.NET Development Server (Cassini), but when the project was deployed to IIS7 the image returned was missing the 3D part and the fancy transparency and shadow effects added through WPF classes, it merely had a blue background, nothing more.

Application Pool advanced settings

The first thing I thought to, are the differences between Cassini and IIS: the former is a process (not a service), it runs under the credentials of the logged on user and also has Administrator rights as Visual Studio does (or should, to work properly). In IIS7 is really easy to test if this was a permission or missing user desktop issue, I changed the Identity property for the application pool to run it under my domain account and changed the Load User Profile to true to have access the my system variables, registry etc…

No luck.

I’ll save you the other tests I’ve done, what is important to know is that there actually is another difference between IIS and Cassini on Windows 2008 / Vista, or I should better say one of the differences I have mentioned before has an important implication on those platforms: services now run in an isolated session (Session 0) while processes run in the session assigned to the user logged on the machine:

Application Compatibility: Session 0 Isolation

In Windows XP®, Windows Server® 2003, and earlier versions of the Windows® operating system, all services run in the same session as the first user who logs on to the console. This session is called Session 0. Running services and user applications together in Session 0 poses a security risk because services run at elevated privilege and therefore are targets for malicious agents that are looking for a means to elevate their own privilege levels.

The Windows Vista® and Windows Server® 2008 operating systems mitigate this security risk by isolating services in Session 0 and making Session 0 non-interactive. In Windows Vista and Windows Server 2008, only system processes and services run in Session 0. The first user logs on to Session 1, and subsequent users log on to subsequent sessions. This approach means that services never run in the same session as users' applications and are therefore protected from attacks that originate in application code.

Specific examples of affected driver classes include:

  • Printer drivers, which are loaded by the spooler service
  • All drivers authored with the User Mode Driver Framework (UMDF) because these drivers are hosted by a process in Session 0

Application classes affected by this feature include:

  • Services that create UI
  • A service that tries to use window-message functions such as SendMessage and PostMessage to communicate with an application
  • Applications creating globally named objects

This can easily been verified adding the “Session ID” column in Task Manager: as you can see, the WinForm client (Test3DInService.exe) is running in Session 2, w3wp.exe is running in Session 0 (despite the fact that the process is running as my domain account and it has loaded the user profile) and finally WebDev.WebServer.exe (Cassini) is running in Session 2:

Windows Sessions

Even more important is this document: Impact of Session 0 Isolation on Services and Drivers in Windows Vista:

Because Session 0 is no longer a user session in Windows Vista, services that are running in Session 0 do not have access to the video driver in Windows Vista. This means that any attempt that a service makes to render graphics fails. In current builds of Windows Vista, querying the display resolution and color depth in Session 0 reports the correct results for the system up to a maximum of 1920x1200 at 32 bits per pixel (bpp).

Got it!

Well, almost, but we’re pretty close. I said the blue background was actually created, and other simple 2D shapes could be successfully rendered as well, so the statement “any attempt that a service makes to render graphic fails” is not fully correct, is should read as “any attempt that a service makes to render graphics that relies on the video driver fails”. Not all graphics need to interact with the video driver so generally speaking, GDI can be used (that’s a different set of libraries than GDI+) and “simple” graphic rendering should normally work fine (as if did in my sample with 2D graphics): the trick is never call (or try to call) into the video driver. This unfortunately means the fancy WPF shadows, transparencies and effects are off limits from a service. It is possible to use BIDs and BIDSection.

I could think to 3 possible solutions (in order of my preference) to this case, not all of them very nice but if nothing else can be done… if you have anything to add, feel free smile_regular:

  • If it is possible to move the logic to create the 3D image, the Web Service call could just return to the client the data needed to build the image and do the “hard work” in WPF either in a Windows Forms client or in Silverlight if you wish
  • Create a sort of custom web server using the hostable web core provided by IIS 7, embed it into a usermode process (not in a service) and use it to run your code and serve the 3D image: this means there must be an account always logged on the server to keep this process running
  • Rely only on “safe and simple” drawing objects or work directly with bytes structures to design your graphic “point by point”: this is the hard way of doing graphics and you’ll need to code it in C++ I think, you’ll likely have to renounce using effects such as transparencies but at least it should work

Carlo

Quote of the day:
A compromise is the art of dividing a cake in such a way that everyone believes he has the biggest piece. - Ludwig Erhard
More Posts Next page »
 
Page view tracker