IHttpAsyncHandler causes UnathorizedAccessException - iis-7

For the last couple of days of my X-mas holidays, I have been struggling with an UnathorizedAccessException when trying to READ a XML file on a remote share through my ASP.NET application using an implementation of the IHttpAsyncHandler a long with the IRequiresSessionState.
After much headache, and concluding that the code OUTSIDE the handler worked flawlessly (see: access granted), I thought it might be some threading issue, so I changed the IHttpAsyncHandler to IHttpHandler, and the problem disappears.
What is troubling me here is, that for test purposes, I did not actually make use if the IHttpAsyncHandler implementation (hence, I did not use BeginProcessRequest and EndProcessRequest - only the sync. version, ProcessRequest.
Can anyone try to explain the issue at hand?
There are some beneficial matters in using the handler asynchronously, as I could pre-cache the values to be delivered later in the application, but for that to work, I have to get pass the security issues that seems to only manifest when implementing the IHttpAsyncHandler.
Thanks in advance for your kind help - and happy holidays :-)

The ASP.NET infrastructure calls an async handler differently (regardless if the impl is truly async). Is it possible that you were relying on impersonation to access the network resource? My guess would be that the necessary WindowsIdentity didn't flow to the threadpool thread that actually handled the request (I've never tried using impersonation + async handler, but I've gotten nailed with other thread state flow issues in the past).
Regardless, a true async handler is expensive to implement correctly. Unless you're building on top of a lot of other async infrastructure (async file i/o, async DB client, etc), it doesn't do you any good (in fact, even in the best cases, async handlers hurt raw performance). I'd look to see if your performance needs really justify the extra hassle and overhead of an async handler (eg, you need to service many more concurrent requests than threads in the process, etc).

Related

Is HttpContextAccessor Thread Safe?

There are two normal ways to access the user's HttpContext, via:
IHttpContextAccessor (and HttpContextAccessor) that are injected for services as so: httpContextAccessor.HttpContext
Or through the controller's property as so: this.HttpContext
In my code base, we make use of both cases. For the usage of HttpContextAccessor, we have them mostly in common singleton services that are shared for every request (such as logging, session handling, etc). I think this should be thread-safe as HttpContextAccessor should know how to handle it, but I see this tweet that throws me off: https://twitter.com/davidfowl/status/907248318538903553
So far it looks okay, but is there any confirmation that it is thread-safe?
You're confusing two different concepts. Thread-safety is only tangentially related to HTTP requests as an HTTP request requires the use of a thread. That's pretty much it, though. HttpContext is request-scoped, so within the context of a single request, you will not have bleed-over, assuming you stay on just one thread or all operating threads run within the context of that particular request.
Where things get wonky is when you start firing off threads that run in the background, i.e. outside the request pipeline. In such situations, HttpContext may or may not exist, or it could be different for the background thread than the original thread. That's where the thread-unsafety comes in.
Long and short, whether or not HttpContext is thread-safe is the wrong question to ask. Instead, you need to ask what work is being done on a thread in what context. If you're in the request pipeline, then HttpContext will effectively be thread-safe, but that would require capturing all threads you fire off, which then pretty much negates the usefulness of using multiple threads. You might as well just do all the work on the original thread. Handling a web request is not the same as something like a desktop or mobile app. In the latter, you need to keep the main or UI thread free, so spinning off threads is a must. The web doesn't work that way; all threads are transient, serving a particular request and then returning to the pool.

ASP.NET thread agility - how to overcome?

ASP.NET is known to exhibit what is called "thread agility". In short, it means that multiple threads may be employed to fulfill a single request, although not more than one thread at a time. This is an optimization that means a thread waiting for asynchronous I/O may be returned to the pool and used to service other requests.
However, ASP.NET does not migrate all thread-related data when moving a request. Microsoft either forgot to do so, or thought that using thread-local storage (made easy by the ThreadStatic attribute) was something only the people coding ASP.NET themselves should do.
Based on quick googling, it seems to me that the only way to avoid the issue is to rely on HttpContext instead. The context is indeed migrated if ASP.NET decides to switch threads mid-request, so this overcomes the problem. But it creates a brand new headache instead: It ties your application logic to HttpContext, and therefore to a web context. That's not acceptable in all situations (in fact, I'd say it's unacceptable in most). Besides, since HttpContext is sealed and has internal constructors, you cannot mock or stub it, and therefore your logic also becomes untestable.
According to this (old) blog post, CallContext does NOT work, which is pretty infuriating given that a call context is conceptually precisely a logical thread!
Is there a simple way to reliably implement "per-LOGICAL-thread" isolation that will work in asp.net contexts as well as other contexts?
If not, does anyone know of a lightweight third-party framework that solves the problem? Does StructureMap behave correctly when ASP.NET migrates threads?
I would like a general answer, but in case anyone wonders, the specific use case I'm looking at is for use of Entity Framework in a SharePoint context. We're unfortunately stuck with SP-2010 and EF 3.5 for a while. EF basically requires that data is saved using the same context as they were originally read from - or else you have to keep track of changes yourself. I would like to introduce a "current model" concept. The first time the model is called upon in processing each HTTP request it should be instantiated, and then that same model instance should be used for the duration of the request. But the code relying on "Model.Current" should also work if executed in the context of a timer job. I'm fine with the timer job code explicitly disposing of the model when done with it (a task I'd like to give to a handler for HttpApplication.EndRequest in the SharePoint web context).
There may be reasons not to do this, and that's interesting too, but I would anyway really appreciate to learn of a way to achieve "logical thread isolation" in an asp.net context, as it'd be remarkably useful.
There is a nice post related to the problem: Implicit Async Context ("AsyncLocal").
If I got everything right, Logical CallContext i.e. CallContext.LogicalGetData and CallContext.LogicalSetData make it real to migrate immutable data correctly given you live in the world past .NET 4.5. This immutable limitation is a nut but still...way to go.

How bad is it to run an entire HTTP action method in separate thread using Task::Run()?

I'm writing web services in C++/CLI (not my choice) using Microsoft's Web API. A lot of functions in Web API are async, but because I'm using C++/CLI, I don't get the async/await support of C# or VB. So the fallback position is to use ContinueWith() to schedule a continuation delegate for reading the async task's result safely.
However, because C++/CLI also doesn't support inline anonymous delegates or managed lambdas, every delegate continuation must be written as a separate function somewhere. That quickly turns into spaghetti with the number of async functions in Web API.
So, to avoid the deadlock issues of Task<T>::Result, I've been trying this:
[HttpGet, Route( "get/some/dto" )]
Task< SomeDTO ^ > ^ MyActionMethod()
{
return Task::Run( gcnew Func< SomeDTO ^ >( this, &MyController::MyActionMethod2 ) );
}
SomeDTO ^ MyActionMethod2()
{
// execute code and use any task->Result calls I need without deadlocking
}
Okay, so I know this isn't great, but how bad is it? I don't yet understand enough of the guts of Web API or ASP.NET to comprehend the performance or scaling ramifications this will have.
Also, what other consequences may this have that aren't necessarily related to performance? For example, exceptions get wrapped in an extra AggregateException, which represents additional complexity and work for handling exceptions.
Your memory usage will increase with your application's parallelism. For every concurrent call to MyActionMethod you will need a separate thread with its own stack. That will cost you about 1 MB of RAM for each concurrent call. If MyActionMethod runs long enough so that 10000 instances run at once, you're looking at 10 GB of RAM. There is also CPU overhead in setting up each thread.
If concurrency is low, dropping async support won't be a problem. In that case, don't bother with Task::Run. Just change MyActionMethod to return SomeDTO^ (no Task wrapper).
Another potential concern is that lose easy use of cancellation tokens. However, for Web API it's usually fine to just let an exception propagate back to Web API, which ends up cancelling the synchronous call anyway.
Finally, if you were planning on performing any operation within your action method in parallel, you'll still need to use ContinueWith to accomplish that. Going non-async by default means you'll always perform one operation at a time. Fortunately, it's often just fine to do so.
Okay, so I know this isn't great, but how bad is it?
It's difficult to answer this without load-testing your specific scenario. But you can walk through the known semantics (taken largely from my blog).
First, when a request comes in, ASP.NET executes your handler on a thread pool thread within that request context. Your request handler calls Task.Run, which takes another thread from the thread pool and executes the actual request logic on it. The handler then returns the task returned from Task.Run; this releases the original request thread back to the thread pool.
Then, the Task.Run delegate will block on any asynchronous parts. So, this pattern has the scaling disadvantages of a regular synchronous handler, plus an extra thread context switch. Also, it uses a thread from the ASP.NET thread pool, which is not necessarily a bad thing, but in some scenarios it may throw off the ASP.NET thread pool heuristics.
Also, what other consequences may this have that aren't necessarily related to performance? For example, exceptions get wrapped in an extra AggregateException, which represents additional complexity and work for handling exceptions.
Yes, the exceptions from any .Result or Wait() calls will be wrapped in AggregateException. You may be able to avoid this by calling .GetAwaiter().GetResult() instead.
Another important consideration is that the code executing within the Task.Run is executing without a request context. So, ambient data like HttpContext.Current, current culture, thread principal, etc. are not going to be set correctly. You'll have to capture any important data before calling Task.Run and pass it down manually.

Asp.net SynchronizationContext locks HttpApplication for async continuations?

This comment by Stephen Cleary says this:
AspNetSynchronizationContext is the strangest implementation. It treats Post as synchronous rather than asynchronous and uses a lock to execute its delegates one at a time.
Similarly, the article that he wrote on synchronization contexts and linked to in that comment suggests:
Conceptually, the context of AspNetSynchronizationContext is complex. During the lifetime of an asynchronous page, the context starts with just one thread from the ASP.NET thread pool. After the asynchronous requests have started, the context doesn’t include any threads. As the asynchronous requests complete, the thread pool threads executing their completion routines enter the context. These may be the same threads that initiated the requests but more likely would be whatever threads happen to be free at the time the operations complete.
If multiple operations complete at once for the same application, AspNetSynchronizationContext will ensure that they execute one at a time. They may execute on any thread, but that thread will have the identity and culture of the original page.
Digging in reflector seems to validate this as it takes a lock on the HttpApplication while invoking any callback.
Locking the app object seems like scary stuff. So my first question: Does that mean that today, all asynchronous completions for the entire app execute one at a time, even ones that originated from separate requests on separate threads with separate HttpContexts? Wouldn't this be a huge bottleneck for any apps that make 100% use of async pages (or async controllers in MVC)? If not, why not? What am I missing?
Also, in .NET 4.5, it looks like there's a new AspNetSynchronizationContext, and the old one is renamed LegacyAspNetSynchronizationContext and only used if the new app setting UseTaskFriendlySynchronizationContext is not set. So question #2: Does the new implementation change this behavior? Otherwise, I imagine with the new async/await support marshaling completions through the synchronization context, this kind of bottleneck would be noticed much more frequently going forward.
The answer to this forum post (linked from SO answer here) suggests that something fundamentally changed here, but I want to be clear on what that is and what behaviors have improved, since we have a .NET 4 MVC 3 app which is pretty much 100% async action methods making web service calls.
Let me answer your first question. In your assumption you didn't consider the fact that separate ASP.NET requests are processed by different HttpApplication objects. HttpApplication objects are stored in pool. Once you request a page, an application object is retrieved from pool and belongs to the request till its completion. So, my answer to your question:
all asynchronous completions for the entire app execute one at a time, even ones that originated from separate requests on separate threads with separate HttpContexts
is: No, they don't
Separate requests are processed by separate HttpApplication objects, locked HttpApplication will affect only single request.
Synchronization context is a powerful thing that helps developers to synchronize access to shared (in scope of request) resources. That is why all callbacks are executed under lock. Synchronization context is a heart of event-based synchronization pattern.

How does ASP.NET webservices route requests do WebMethods?

I'm having problems because of a poorly written third-party library which our system heavily depends on. This library is not thread-safe (because of some bugs and static variables) and I need to use it in a ASP.NET webservice, which handles each user request in a separate thread.
I've tried many solutions for this problem. The best solution for now is, in my opinion, let subprocesses handle the requests. One subprocess will listen and handle the requests for one user, so I can synchronize access to the library code in a per user fashion, which is much better than all that I can do when sharing static variables between requests.
How can I route requests received by IPC communication to the appropriate WebMethods without reinventing the wheel? If possible, I would like to use the classes from .Net that handle this in a normal ASP.NET webservice, but I'm having a hard time trying to find their names.
TL;DR: I have a class MyWebService (that inherits from System.Web.Services.WebService) with some methods marked with WebMethodAttribute and I want to pass a made-up HttpRequest (or HttpContext) to it and tell it "handle it like you're receiving this from a real HTTP server, despite the fact the current process is a console application".
First, you may want to consider using WCF instead of ASMX, which is a legacy technology, kept only for backwards compatibility.
Second, you have another option: ensure that only a single thread ever uses the third-party libarary at a time. Placing lock blocks around all access to the third-party library may solve the problem.

Resources