locked
System.Threading ThreadPool and ThreadStatic Attribute RRS feed

  • Question

  • Consider the following situation. A server implements an RPC solution, displatching requests from multiple users using the default ThreadPool. Dispatching of requests may involve lengthy operations, such as accessing the database. Each dispatched request (on its own ThreadPool thread) maintains a static variable marked with ThreadStatic Attribute, initializing its contents prior to executing business logic and cleaning up afterwards. Consider this as a way to provide an additional parameter to all functions executing on a thread.

    Intermittently, however, the contents of this ThreadStatic variable leak between ThreadPool workers. Meaning that the contents of the variable is not what it is expected by the worker, but actually belongs to another worker.

    To better understand how to localize the problem, I have a question. Considering the described hypothetical situation, is it possible that ThreadPool suspends a worker blocked on a lengthy operation (e.g. waiting for database query results), and then resumes it on a different thread? Another possibility is to suspend a blocked worker, schedule execution of another worker on the same thread, and then resume the original worker on the same thread. Either way, the idea is that the resumed worker might inherit the ThreadStatic variable initialized by another worker.

    Technically, it is possible, as BCL provides a way to save and restore thread stack, operation cost notwithstanding. The question is if ThreadPool is designed to do that.
    Monday, August 18, 2008 4:09 PM

Answers

  • Yes, that can't be it.  Getting the execution context to hop from one thread to another is very difficult to do and requires explicit code such as a delegate's BeginInvoke() method.  That this is possible at all is definitely one of the shining achievements in the CLR but it is certainly not going to happen by accident.

    I'd focus on the RPC angle.  RPC invokes methods in the stub with a threadpool thread too, it will pick a pool thread for each individual method invocation.  On the server side, the code will run on one thread, on the client side it can run on any number of threads.  The COM apartment threading model was invented to avoid problems with that.  Apartment threading is easy to ignore in .NET code.  One thing that is especially tricky with this is that RPC tends to reuse the same pool thread over and over again, once in a great while having to pick another one because the original one is busy with something.  I vaguely remember reading something about a registry setting that forces RPC to cycle threads, designed to flush this kind of threading problem out.  Sorry, that synapse went dormant a while ago.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Friday, August 22, 2008 1:41 PM
    Tuesday, August 19, 2008 10:32 AM

All replies

  • >  is it possible that ThreadPool suspends a worker blocked on a lengthy operation (e.g. waiting for database query results), and then resumes it on a different thread?

    Highly unlikely.  The whole idea of blocking operations is that they block the calling thread.

    If .NET was able to do what you suggest, I think it would mess up things like TransactionScope.
    Tuesday, August 19, 2008 12:29 AM
  • Yes, that can't be it.  Getting the execution context to hop from one thread to another is very difficult to do and requires explicit code such as a delegate's BeginInvoke() method.  That this is possible at all is definitely one of the shining achievements in the CLR but it is certainly not going to happen by accident.

    I'd focus on the RPC angle.  RPC invokes methods in the stub with a threadpool thread too, it will pick a pool thread for each individual method invocation.  On the server side, the code will run on one thread, on the client side it can run on any number of threads.  The COM apartment threading model was invented to avoid problems with that.  Apartment threading is easy to ignore in .NET code.  One thing that is especially tricky with this is that RPC tends to reuse the same pool thread over and over again, once in a great while having to pick another one because the original one is busy with something.  I vaguely remember reading something about a registry setting that forces RPC to cycle threads, designed to flush this kind of threading problem out.  Sorry, that synapse went dormant a while ago.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Friday, August 22, 2008 1:41 PM
    Tuesday, August 19, 2008 10:32 AM
  • Thanks for replying.

    That was a wild idea to begin with. I guess the problem is with the RPC server code, which does not clean up the contents of the said ThreadStatic variable under some unforeseen conditions.
    Tuesday, August 19, 2008 4:36 PM