I have a complex server application that uses Nhibernate and Linq2SQL. About 3 times per day the Linq2sql code generates a “value cannot be null” exception. Once this happens, the code will always generate the exception. Diagnosis and solving the root cause will be lengthy and will introduce instability.
The current “fix” is to recyle the app pool every hour. However, the service is down from the point the problem happens until the recycle occurs. I want the web service to catch the exception and recycle it’s own app pool. I want all other web requests to be honored until they are completed.
Edit: The fault is on both servers on a load balanced web farm. Clients do not switch from one server to the other just because this code crashes.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The following code will recycle the current site’s app pool. You need to add a reference to Microsoft.Web.Administration
using (ServerManager iisManager = new ServerManager())
{
SiteCollection sites = iisManager.Sites;
foreach (Site site in sites)
{
if (site.Name == HostingEnvironment.SiteName)
{
iisManager.ApplicationPools[site.Applications["/"].ApplicationPoolName].Recycle();
break;
}
}
}
Method 2
The simplest way to “trip” the ASP.NET worker process into recycling an application pool is to modify the web.config file in some way. This change is picked up by the file system watcher and causes ASP.NET to recycle in order to load the new configuration.
The content of the file doesn’t have to change in any practical way; just adding or removing whitespace character is enough.
Edit:
If this isn’t strong enough to work around your problem, you can go the whole hog and use Directory Services to recycle the app pool manually.
// Set up the path identifying your application pool.
var path = "IIS://YOURSERVERNAME/W3SVC/AppPools/YourAppPoolName";
// Create the directory entry to control the app pool
var appPool = new DirectoryEntry(path);
// Invoke the recycle action.
appPool.Invoke("Recycle", null);
Based on Code Project: Recycling IIS 6.0 application pools programmatically.
Method 3
I’ve had the exact same problem before; I should have blogged about it because now I can’t remember the root cause.
My gut tells me, it was one of the following:
- A context not getting disposed somewhere.
- Threading issue: make sure multiple threads can’t access the same context.
Or something along those lines. Just make sure you’re using Linq2Sql correctly.
Method 4
The solution I eventually chose was to set a maximum value for the amount of memory the appPool was allowed to consume. The code then simply gobbled memory until asp.net decided to recycle the appPool.
In the App pool advanced settings I set the Private Memory Limit to 800,000 Kb.
In the Catch section where the Linq code failed, I allocate more memory than the limit:
List<string> listOfMemory = new List<string>();
// in the app pool, you need to set the virtual memory limit to 800,000kb
log.Error("Allocating so much memory that the app pool will be forced to recycle... ");
for (int intCount = 1; intCount < 10000000; intCount++)
{
listOfMemory.Add("new string " + intCount.ToString());
}
This now means only about 4 threads fail before a new w3wp process is spawned. Prior to this solution, threads would consistently fail until a human recycled the app pool manually. Unfortunately, if you set the app pool to recycle on a regular number of minutes, the smaller the number of minutes the more often the crash. And the larger the number of minutes, the more threads would fail.
This creative workaround limits the damage.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0