Scott on Writing

Musings on technical writing...

URL Rewriting Redux

Alert reader Gustavo Garcia emailed me recently with a small bug he found in my URL Rewriting in ASP.NET article:

I think the code:

 if (HttpContext.Current.Cache["RewriterConfig"] == null)
  HttpContext.Current.Cache.Insert("RewriterConfig",
ConfigurationSettings.GetConfig("RewriterConfig"));
 
 return (RewriterConfiguration)
HttpContext.Current.Cache["RewriterConfig"]; //Could return NULL?!?!?!?

could produce race conditions, because the Cache could be freed between if
and return.
 
 RewriterConfiguration config =
(RewriterConfiguration)HttpContext.Current.Cache["RewriterConfig"];
 if (config == null)
 {
  config = ConfigurationSettings.GetConfig("RewriterConfig");
  HttpContext.Current.Cache.Insert("RewriterConfig", config);
 }
 return config;

Best regards, and thank you for your article.

Good catch, Gustavo.  This problem is discussed with a good explanation in Scott Cate's blog entry: Steve Smith's Awesome Caching Pattern.

Speaking of URL rewriting in ASP.NET, the #1 question I get is with regards to mapping all requests to the aspnet_isapi.dll ISAPI Extension.  The blog engine software that I use to run this blog - .Text (or Community Server :: Blogs, as it will be called) - heavily utilizes URL rewriting and provides an option where all incoming requests can be mapped to the ASP.NET engine.  So why not turn to Scott Watermasysk - creator of .Text - for some explanation on this?  Scott recently posted an entry on some issues with mapping all requests to the ASP.NET process, including tasks you'll have to do once this mapping is made.

posted on Wednesday, September 08, 2004 10:51 AM

Feedback

# re: URL Rewriting Redux 9/8/2004 12:57 PM Adam

You can still have a race condition in your code here. Two threads (two separate requests) could get a null reference to the config and both attempt to insert. You really should be locking to be thread safe.

private static object ConfigLockObject = new object();

RewriterConfiguration config = null;
if( HttpContext.Current.Cache["RewriterConfig"] == null ) {
lock( ConfigLockObject ) {
// you have to check a second time since multiple threads
if( HttpContext.Current.Cache["RewriterConfig"] == null ) {
config = ConfigurationSettings.GetConfig("RewriterConfig");
HttpContext.Current.Cache.Insert("RewriterConfig", config);
}
}
}
else {
config = (RewriterConfiguration) HttpContext.Current.Cache["RewriterConfig"];
}

# re: URL Rewriting Redux 9/8/2004 12:59 PM Adam

My code above missed an else statement:

private static object ConfigLockObject = new object();

RewriterConfiguration config = null;
if( HttpContext.Current.Cache["RewriterConfig"] == null ) {
lock( ConfigLockObject ) {
// you have to check a second time since multiple threads
if( HttpContext.Current.Cache["RewriterConfig"] == null ) {
config = ConfigurationSettings.GetConfig("RewriterConfig");
HttpContext.Current.Cache.Insert("RewriterConfig", config);
}
else {
config = (RewriterConfiguration) HttpContext.Current.Cache["RewriterConfig"];
}
}
}
else {
config = (RewriterConfiguration) HttpContext.Current.Cache["RewriterConfig"];
}

# re: URL Rewriting Redux 9/8/2004 1:06 PM Scott Mitchell

Adam, I don't disagree with you w.r.t. the race condition, but I fail to see how this is a "big deal." Can you explain what can go awry in the above situation? Why would it matter if two threads insert the same value to the cache?

# re: URL Rewriting Redux 9/8/2004 3:01 PM Adam

I didn't say it was a big deal, I just said it fixes the race condition that the supplied fix doesn't actually fix (since it wasn't synchronizing access to a critical section of code).

# re: URL Rewriting Redux 9/23/2004 11:15 AM Scott Allen

Scott:

I think it's a great article.

Something I learned from working with the CSK is the action attribute in the form tag can be set properly by calling RewritePath a second time during the request inside the page's Load event - it's a one liner you could stick in a base class. See http://odetocode.com/Blogs/scott/archive/2004/09/22/509.aspx/

# re: URL Rewriting Redux 1/19/2006 11:50 PM François

Anyway, caching the configuration settings in your context is useless as far as I know. The configuration system is cached. You can try it yourself by making a custom IConfigurationSectionHandler, and calling ConfigurationSettings.GetConfig several times, even in separate threads, you will always get the same object. Which again raises a situation dangerous for thread safety : for example, the NameValueSectionHandler returns a NameValueCollection, what happens if in a thread jokes around by adding or updating a value in the collection while somebody else is reading the collection ? Of course, it's not a good practice to update configuration settings on your code, but I'm somewhat astonished that the configuration system doesn't return a copy of the object given by your configuration handler, making the implementation ICloneable mandatory.

By the way, configuration settings are like any static variables, they are the same in the same application domain. And when the web.config file is updated, ASP.NET reloads the application domain, including flushing the configuration cache. But I guess it wouldn't cause a problem in your code since your HttpContext will be flushed too :) If you have any wuestion, you can reach me at sossalemaire at yahoo.fr...

# UrlRewriter Bug Fix 2/12/2006 5:15 PM Steven Smith

Some of you may know that I'm pretty interested in caching as a means to improving performance. ...

# Upcoming Talk at the SoCal .NET Technical Summit 8/24/2006 7:28 AM Scott on Writing

# Upcoming Talk at the SoCal .NET Technical Summit 8/24/2006 7:56 AM Community Blogs

On Saturday, September 23rd, I'll be speaking at the SoCal .NET Technical Summit in Irvine, CA at the

Title:  
Name:  
Url:
Protected by Clearscreen.SharpHIPEnter the code you see:
Comments   

Add To Your Reader

My Links

Archives

Post Categories

 

I am a Microsoft MVP for ASP.NET.
I am an ASPInsider.
<May 2008>
SMTWTFS
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Comment Stats

DayTotal% of Total
Sunday 1866.8%
Monday 37913.9%
Tuesday 45316.7%
Wednesday 50418.5%
Thursday 53519.7%
Friday 49418.2%
Saturday 1666.1%
Total 2717100.0%

Hour1Total% of Total
12:00 AM 652.4%
1:00 AM 682.5%
2:00 AM 622.3%
3:00 AM 742.7%
4:00 AM 572.1%
5:00 AM 1033.8%
6:00 AM 1084.0%
7:00 AM 1585.8%
8:00 AM 1716.3%
9:00 AM 1475.4%
10:00 AM 1716.3%
11:00 AM 1816.7%
12:00 PM 1886.9%
1:00 PM 1696.2%
2:00 PM 1605.9%
3:00 PM 1324.9%
4:00 PM 1073.9%
5:00 PM 923.4%
6:00 PM 913.3%
7:00 PM 963.5%
8:00 PM 833.1%
9:00 PM 782.9%
10:00 PM 792.9%
11:00 PM 772.8%
Total 2717100.0%

Comments by Blog Entry Date/Time

Day Entry MadeAvg.Total
Sunday 5.54144
Monday 5.22339
Tuesday 4.28419
Wednesday 7.67637
Thursday 6.90607
Friday 5.48411
Saturday 5.33160
Total 5.842717

Hour1 Entry MadeAvg.Total
12:00 AM 5.0035
1:00 AM 1.002
5:00 AM 0.000
7:00 AM 7.0035
8:00 AM 5.35107
9:00 AM 6.32278
10:00 AM 6.47246
11:00 AM 4.41181
12:00 PM 6.88330
1:00 PM 3.00111
2:00 PM 5.41222
3:00 PM 8.64285
4:00 PM 4.0589
5:00 PM 5.92154
6:00 PM 4.52113
7:00 PM 9.67174
8:00 PM 9.80147
9:00 PM 5.05111
10:00 PM 5.4265
11:00 PM 4.5732
Total 5.842717

Learn More About Comment Stats
1 - All times GMT -8...


Blog Stats

Favorite Web Sites

My Books

My MSDN Articles