Archive for June 2014
This article was originally published for www.prowareness.com and could be located at http://www.prowareness.com/blog/let-your-iis-worker-process-crash-with-stackoverflowexception/
Months back I posted a screenshot at https://renouncedthoughts.wordpress.com/2013/12/05/system-stackoverflowexception-in-mscorlib-dll/, finally got time to write it down.
There was a Login page, that did some sort of authorization check beyond authenticating the user, and displayed an Access Denied page for those who weren’t lucky enough. This was all done by the ASP.NET MVC with ASPX view engine. So there’s things like Views, Partial Views, RenderPartial, and so on. The application also was heavily ajax enabled, so partial views really seemed to fit in at many places that did not want to include a master page content in the response text. There was a view file called AccessDenied.aspx that barked at unauthorized users. Things were working fine, and one day something broke, IIS was crashing without any meaningful error message. I lied, actually it did give a meaningful error message that was like – An unhandled exception of type ‘System.StackOverflowException’ occurred in mscorlib.dll. And the Call Stack showed some recursive function call. That is all there was to it.
Let’s look at a POC sample application below. Download the source from github – https://github.com/gmaran23/ASPXViewEngineCrash, Hit F5.
When you click the AccessDeniedForCrash page, the below is what you see. An unhandled exception of type ‘System.StackOverflowException’ occurred in mscorlib.dll. If you look at the Call Stack window, there would be a lot of repeated method calling method.
Let’s look at what happens when a view is requested, as in how the view engine probes the known locations to find the view definition. Click ViewDoesNotExist, and you would see an error page, that actually tells you the file locations that ASPX view engine probed to find a matching view. Pay attention to the search order where a .aspx file is searched first, and then the .ascx file.
Now, if you go back to the StackOverflowExceptionInASPXViewEngine solution, there are two files called AccessDeniedForCrash.ascx and AccessDeniedForCrash.aspx under ~/Views/Home.
The following code inside AccessDeniedForCrash.aspx calls the partial view AccessDeniedForCrash.ascx.
A typical programming practice right? You define sub routines, and you keep calling them as and when required. Reusability! You have created a partial view here (AccessDeniedForCrash.ascx), and kept calling the partial view inside the main view (AccessDeniedForCrash.aspx). But it was the ASPX view engine’s probing method that caused the recursive method call. The view engine reached AccessDeniedForCrash.aspx, as it came through the HomeController’s action method AccessDeniedForCrash. It tried to find a partial view AccessDeniedForCrash.ascx, but always ended up with AccessDeniedForCrash.aspx because of the file search order; you know the rest of the story about recursion without an exit condition.
So, is this a programming error? or the framework error? or the ‘programmer did not understand the framework well’ error?