EL5 Caching Block ICacheRefreshAction - Strange Thread Identity problem

Topics: Caching Application Block
Sep 10, 2013 at 10:27 AM
Hi there,

I'm currently working on a Windows forms application which uses WCF hosted in IIS for backend access.

We use the Enterprise Library caching block in the client application to store a small amount of lookup data which is frequently required within the application. In order to ensure a level of consistency with the data, we are using a custom refresh action with an expiration time which will retrieve the current lookup data via a WCF method. As far as I understand this, this refresh request runs on a background thread generated within the Enterprise Library code.

On the server side, we are using a custom authorization policy to authenticate client requests. WCF is set up to run in PerCall mode.

In production, the client application runs on a Citrix environment.

The behaviour we are seeing is that the caching block refresh action is causing an identity issue on the threads arriving at the server. If we have a request pattern as follows occurring in this order within a very small timeframe:
  • 1: Client A requests data - on server, Thread.CurrentPrincipal is Client A (Correct)
  • 2: Client B triggers the cache refresh action - on server, Thread.CurrentPrincipal is Client B (Correct)
  • 3: Client A requests data again - on server, Thread.CurrentPrincipal is Client B - eh?
We have confirmed from WCF tracing that the same thread has been used for all of the above operations. I have yet to come up with a theory of how this is possible - but it does seem as if the next request after a request from the refresh action already has Thread.CurrentPrincipal set to a WindowsIdentity. Every other request from the client will have the application pool identity and we authenticate the client and set the principal to the correct identity which is used thereafter.

The fix for this is very easy for us to implement - there was some legacy code which was skipping over the correct authentication process. However, I thought I would post this to see if anyone else has ever come across this strange behaviour?

If I remove the refresh action from the cache, we do not get this problem. I have also written a quick implementation of System.Runtime.Caching and ran some tests with that - again, the problem no longer occurs. So it does look as if the EL5 caching block is causing this issue - does anyone have any idea as to why? :)
Editor
Sep 11, 2013 at 12:49 AM
The reason for the behavior you are seeing is that the ICacheItemRefreshAction is executed on a ThreadPool thread. These threads are the same ones that IIS uses to service requests. So, if you are setting custom information on the thread then it is likely that when the ICacheItemRefreshAction runs it will obtain different thread specific values than the thread that serviced the request.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Sep 11, 2013 at 4:04 PM
I'm not doing anything different in the refresh action request than a "normal" client request - it will run through the same WCF client as the rest of the application. Inspecting this at runtime, the value for Thread.CurrentPrincipal is the same - the WindowsIdentity of the logged in user.

I realise that this is running on a ThreadPool thread - but the problem is occurring after the thread which has been used by the ICacheItemRefreshAction has been returned to the ThreadPool. This thread is then re-used by another WCF request arriving at the server - why does this thread already have a Thread.CurrentPrincipal with the Windows Identity of the user who triggered the ICacheItemRefreshAction ? Surely it should be the Application Pool Identity regardless of what the previous operation on that thread was?

If a "normal" thread (i.e. not previously used by the RefreshAction) is used to service a WCF request, it will be retrieved from the ThreadPool and will always have the Application Pool Identity.
Editor
Sep 11, 2013 at 5:31 PM
All Enterprise Library does is call ThreadPool.QueueUserWorkItem so any setting of Thread.CurrentPrincipal would be done by the application/.NET runtime (and perhaps the custom ICacheItemRefreshAction if applicable).

Setting Role-Based Security Policy and Principals has some interesting reading. Are you using impersonation? When the thread pool thread is invoked the current principal is propagated so perhaps this results in the CurrentPrincipal being explicitly set which overrides the behavior of returning the application domain's default.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Sep 12, 2013 at 12:50 PM
Hi Randy,

Thanks for that link - this part would seem to cover it:

"In the .NET Framework version 2.0, when a thread starts another thread or queues a work item for execution by the thread pool, the thread's context (including the security principal) automatically flows to the child thread or the thread pool thread. In the .NET Framework versions 1.0 and 1.1, context flowed only to threads started by a thread, and not to thread pool threads."

As you say, the part in bold does seem to be overriding the behaviour of the application domain.

Thanks again,

Paul.