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   

My Links

Ads Via DevMavens

Archives

Post Categories

 

I am a Microsoft MVP for ASP.NET.
I am an ASPInsider.
<March 2010>
SMTWTFS
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Comment Stats

DayTotal% of Total
Sunday 2056.8%
Monday 42514.1%
Tuesday 51917.2%
Wednesday 55618.4%
Thursday 58019.2%
Friday 54718.1%
Saturday 1886.2%
Total 3020100.0%

Hour1Total% of Total
12:00 AM 782.6%
1:00 AM 812.7%
2:00 AM 682.3%
3:00 AM 822.7%
4:00 AM 692.3%
5:00 AM 1264.2%
6:00 AM 1193.9%
7:00 AM 1816.0%
8:00 AM 1926.4%
9:00 AM 1585.2%
10:00 AM 1886.2%
11:00 AM 1936.4%
12:00 PM 2016.7%
1:00 PM 1846.1%
2:00 PM 1695.6%
3:00 PM 1354.5%
4:00 PM 1153.8%
5:00 PM 1073.5%
6:00 PM 1013.3%
7:00 PM 1073.5%
8:00 PM 923.0%
9:00 PM 882.9%
10:00 PM 913.0%
11:00 PM 953.1%
Total 3020100.0%

Comments by Blog Entry Date/Time

Day Entry MadeAvg.Total
Sunday 5.00160
Monday 4.80384
Tuesday 4.04477
Wednesday 7.39680
Thursday 6.26676
Friday 5.07466
Saturday 4.78177
Total 5.403020

Hour1 Entry MadeAvg.Total
12:00 AM 5.2937
1:00 AM 1.002
5:00 AM 0.000
7:00 AM 3.8550
8:00 AM 3.72134
9:00 AM 6.06297
10:00 AM 5.63276
11:00 AM 4.22194
12:00 PM 6.16351
1:00 PM 3.09133
2:00 PM 4.89230
3:00 PM 7.67322
4:00 PM 4.00108
5:00 PM 6.07170
6:00 PM 4.64116
7:00 PM 8.95188
8:00 PM 8.63164
9:00 PM 5.00115
10:00 PM 6.31101
11:00 PM 4.5732
Total 5.403020

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


Blog Stats

Favorite Web Sites

My Books

My MSDN Articles