locked
Does IErrorHandler catch all exceptions ? RRS feed

  • Question

  • Hi all,
    While developing a WCF application I have implemented IErrorHandler interface to implement a generic error handler, however I have found that the HandleError ( and ProvideFault )routine gets fired only the if the exception raised in the WCF request processing thread, for example if I am fork a thread( from WCF request processing thread) and do something in that thread, and for some reason if the thread code throws an exception, that exception not get caught by the IErrorHandle routines and that exception considered as an ‘UnhandleExceptions’ which ultimately terminate the worker process( I have hosted the WCF service in IIS ).

     

    I have designed a custom attribute which implement IServiceBehavior, and has been used by all the WCF methods  as mentioned below……

    [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, AllowMultiple=false)]

        public sealed class FaultExceptionHandlerAttribute : Attribute, IServiceBehavior

        {

                    ……………….

                                   

                    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)

            {

                foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)

                {

                    dispatcher.ErrorHandlers.Add(new FaultExceptionHandler());

                }

            }

      }

     

    The WCF methods have used this attributes as mentioned below ..

    [FaultExceptionHandlerAttribute]

            public string Foo(string message)

            {

              

    And this is my IErrorHandle.HandleError routine …….

    public bool HandleError(Exception error)

            {

                Helper.LogException(error.Message, null);

                return true;       

            }

     

    I wanted to know two things …

    A.      Whether it is a known behavior ? if yes how to make sure that all the exceptions(includes exception thrown by forked threads) will be handled by IErrorHandler.HandleError

     

    B.      Am I missing something ?

     
    Thanks,
    Gautam

    Monday, December 8, 2008 12:39 PM

Answers

  • Hi Will,

    It seems you need synchronization: you need to provide your client with result of background thread. So it means that you need to idle wcf request thread unless your worker thread is completed.
    So here is two cases I can imagine (choose the right one which is more applicable for you):

    1. Your wcf request thread spawns/uses only one background thread, waits until it finishes execution, then returns response to client. In this case I believe that you'd need to review your design. Because when it comes to such synchronization, it's better to perform all operations in wcf request thread. Anyway, your request thread will end up waiting.

    2. Your wcf request thread spawns/uses several (more than one) background threads. Then you need to implement IAsyncResult pattern/interface in .NET or use existing one available for delegates (BeginInvoke, EndInvoke). In this case when all background threads finish execution (you can wait for them by using WaitHandle.WaitAll (wait handles of all your background threads)) and then retrieve result (in case of delegates it would be EndInvoke). You do not need to handle any exceptions here, because all background thread exceptions will be raised on request thread and automatically handled by IErrorHandler.

    Vitaliy Liptchinsky http://dotnetframeworkplanet.blogspot.com/
    • Marked as answer by Marco Zhou Tuesday, December 16, 2008 9:56 AM
    Tuesday, December 9, 2008 3:40 PM
  • -> I found that if we call the EndInvoke() from the WCF request processing thread, and then only the excetpion get handled by the IErrorHandlder.

    WCF could only catch the exceptions raised from the thread which invokes the service operation, it cannot and impossible for WCF to catch the exceptions raised from the thread forked by the service operation.

    If you are worrying that the asynchronous exception raised by the worker thread will torn down the service host, you could simply hook up to AppDomain.UnhandledException handler.

    Thanks

    Edit: Delete the incorrect statement to prevent false info propagation.

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Edited by Marco Zhou Tuesday, December 16, 2008 9:56 AM bad typo
    • Marked as answer by Marco Zhou Tuesday, December 16, 2008 9:57 AM
    Wednesday, December 10, 2008 9:10 AM

All replies

  • Hello,

    A. It is known behavior. IErrorHandler handles only exceptions from worker threads.
    B. I wouldn't host background threads under IIS. IIS is well tuned for short-living http requests. IIS can, for instance, recycle application domain and kill your background thread when there is no worker threads.

    Vitaliy Liptchinsky http://dotnetframeworkplanet.blogspot.com/
    Monday, December 8, 2008 12:56 PM
  • Vitaliy,

    I am seeing the same behavior with a Windows Service as my host. How would you suggest I prevent these unhandled exceptions from killing the service given that I have a Windows Service as a host?

    Thanks,
    Will.
    Monday, December 8, 2008 2:35 PM
  • Will,

    I know only one good approach of handling exceptions in background thread:

    try
    {
    MyMainBackgroundThreadMethod();
    catch(Exception ex)
    {
    //Handle here your exception
    }

    In other words, manage it by your code.
    If you want to avoid code duplication in exception handling you can create common class that will be called in IErrorHandler and in catch clause of background threads.

    Vitaliy Liptchinsky http://dotnetframeworkplanet.blogspot.com/
    Monday, December 8, 2008 8:32 PM
  • Thanks Vitaliy,

    So, it looks like I have to write code to handle expection in the worker threads.

    btw, I have liked your idea of calling IErrorHandler from the catch block of worker thread code, doing that we can keep a singler handler (sort of handling exception in one place), however in that case we have to design IErrorHandle::HandleError routine with caution, we should not use context objects say OperationContext inside this routine, because OperationContext is thread static, and the worker thread will have no informaion on OperationContext unless we attach it with the worker thread. (reason being I am saying it cause I have seen couple of IErrorHandler::HandleError implementation, where the coder use OperationContext[ OperationContext.Current ] object inside this routine).

    Thanks again,

    Gautam

     

     

     

    Tuesday, December 9, 2008 10:52 AM
  • Guatam,

    Here is a bit misunderstanding. Actually I meant to create common class, called for instance ExceptionHandler and use this class in both IErrorHandler and catch clause in background thread. This would prevent you from being aware where this class is called from. This common class should not depend on OperationContext or any other WCF classes.

    Or you could implement IErrorHandler interface in your ExceptionHandler class and additional interface for background threads. But internall both interfaces would call the same method.

    Vitaliy Liptchinsky http://dotnetframeworkplanet.blogspot.com/
    Tuesday, December 9, 2008 11:03 AM
  • Thanks Vitaliy, now understood your point.

    Tuesday, December 9, 2008 2:39 PM
  • Vitaliy,

    I think I misstated my ultimate goal. I realize that I can catch and trap all worker thread exceptions to prevent the Windows Service from crashing. What I would like to be able to do is have these exceptions propagated back to my client as they normally would be if they had occured on a single-threaded service operation. My goal is to be able to communicate service operation errors back to the client regardless if the service operation makes use of worker threads or not.

    If I throw an exception from a single-threaded service operation WCF takes care of passing it to my IErrorHandler implementation, wherein I convert it to a Fault and pass it back to my client.

    If I throw an exception from a raw worker System.Thread of a service operation, marshal it back to the main thread, catch it, and then rethrow it from the main thread, it blows up my windows service. It's like it's "out of band" from the WCF stack at that point. I'd like to have this re-throw behave the same as an exception from a single-threaded service operation.

    Any suggestions?
    Thanks.

    Tuesday, December 9, 2008 2:42 PM
  • Hi Will,

    It seems you need synchronization: you need to provide your client with result of background thread. So it means that you need to idle wcf request thread unless your worker thread is completed.
    So here is two cases I can imagine (choose the right one which is more applicable for you):

    1. Your wcf request thread spawns/uses only one background thread, waits until it finishes execution, then returns response to client. In this case I believe that you'd need to review your design. Because when it comes to such synchronization, it's better to perform all operations in wcf request thread. Anyway, your request thread will end up waiting.

    2. Your wcf request thread spawns/uses several (more than one) background threads. Then you need to implement IAsyncResult pattern/interface in .NET or use existing one available for delegates (BeginInvoke, EndInvoke). In this case when all background threads finish execution (you can wait for them by using WaitHandle.WaitAll (wait handles of all your background threads)) and then retrieve result (in case of delegates it would be EndInvoke). You do not need to handle any exceptions here, because all background thread exceptions will be raised on request thread and automatically handled by IErrorHandler.

    Vitaliy Liptchinsky http://dotnetframeworkplanet.blogspot.com/
    • Marked as answer by Marco Zhou Tuesday, December 16, 2008 9:56 AM
    Tuesday, December 9, 2008 3:40 PM
  • Hi Vitaliy,

    One comment on point 2.  If we call the EndInvoke from a different thread( than the WCF request processing thread/ asynch call Invoker thread) and if that code throws an exception, do you mean to say in this case the exception will be handled by IErrorHandler ? [ please correct me if I have misunderstod the point]

    I found it doesn't happen, please consider the following code ....

    [Variable declared at class level]
    WaitCallback waitCallBack;
    ManualResetEvent resetEvent = new ManualResetEvent(false);

    [FaultExceptionHandlerAttribute] //WCF method, this custom attribute makes sure the IErrorHandler will get called upon an exception occrus.
    public string Foo(string message)
    {
       waitCallBack = DoSomething;
       waitCallBack.BeginInvoke(
    null, AsynchCallFinished, null);
       resetEvent.WaitOne();
       return "Hello  " + message;
    }

    private void DoSomething(Object state)
    {
       throw new NotImplementedException("Sorry not yet implemented.");
    }

    private void AsynchCallFinished(IAsyncResult state)
    {
      try
        {
          waitCallBack.EndInvoke(state);  //End Invoke is called without a CATCH block
        }
        finally
        {
          resetEvent.Set();
        }
    }

    Please let me know your comments on the above.

    I found that if we call the EndInvoke() from the WCF request processing thread, and then only the excetpion get handled by the IErrorHandlder.

    Thanks,
    Gautam.

    Wednesday, December 10, 2008 7:07 AM
  • -> I found that if we call the EndInvoke() from the WCF request processing thread, and then only the excetpion get handled by the IErrorHandlder.

    WCF could only catch the exceptions raised from the thread which invokes the service operation, it cannot and impossible for WCF to catch the exceptions raised from the thread forked by the service operation.

    If you are worrying that the asynchronous exception raised by the worker thread will torn down the service host, you could simply hook up to AppDomain.UnhandledException handler.

    Thanks

    Edit: Delete the incorrect statement to prevent false info propagation.

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Edited by Marco Zhou Tuesday, December 16, 2008 9:56 AM bad typo
    • Marked as answer by Marco Zhou Tuesday, December 16, 2008 9:57 AM
    Wednesday, December 10, 2008 9:10 AM
  • Thanks Marco for confirming the IErrorHandler behavior,

    One point though, if I am correct you wanted to mean that handling exception in AppDomain.UnhandledException handler will stop terminating the process, am I correct ?

    if you have meant so, it's not correct anymore in .NET 2.0, I have copied the following from MSDN ...
    In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurred in a thread other than the main application thread was caught by the runtime and therefore did not cause the application to terminate. Thus, it was possible for the UnhandledException event to be raised without the application terminating.
    In the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug.


    Please  let me knwo your thought.

     

     

    Wednesday, December 10, 2008 9:26 AM
  • Hi Guatam,

    Yes, you need to call EndInvoke from your wcf request thread.

    Vitaliy Liptchinsky http://dotnetframeworkplanet.blogspot.com/
    Wednesday, December 10, 2008 9:26 AM
  • Yes, the behavior is changed, then you'd better call the EndInvoke method on the service request processing thread.

    Thanks

    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Thursday, December 11, 2008 7:17 AM