locked
Catch all exceptions except one RRS feed

  • Question

  • Is there a way to catch all exceptions except one?

     

    What for? I've got an WCF service, and since any exception other than FaultExceptions fault the communication channel I want to let pass FaultExceptions, but catch every other exception.

     

    Right now I use this:

    try

    {

      [... my code ...]

    }

    catch (FaultException)

    {

      throw;

    }

    catch (Exception ex)

    {

      throw new FaultException<Exception>(ex);

    }

     

    I catch FaultExceptions and rethrow them. Is this a good way to convert all other exceptions to FaultExceptions?

     

    Thanks,
    Sam

     

    Thursday, July 19, 2007 10:21 AM

Answers

  • Just have one catch that catches everything, test to see if it's a FaultException, and if it is throw it.
    Thursday, July 19, 2007 12:24 PM

All replies

  • Just have one catch that catches everything, test to see if it's a FaultException, and if it is throw it.
    Thursday, July 19, 2007 12:24 PM
  • I don't recommend doing something like that.  I would catch the exceptions that are documented to occur, there are some exceptions you can't handle unless you know the thread you're on isn't going to continue running.  StackException and OutOfMemory are classic examples; if you catch all exceptions but "FaultException" you wouldn't be passing along StackException or OutOfMemory exception and would be "hiding" that problem.  Code farther up the stack would continue to run even though you're pretty much guaranteed that they'll fail.
    Thursday, July 19, 2007 2:27 PM
    Moderator
  • Peter,

     

    if you have looked at my source you should have noticed that I do not hide exceptions. I only transform them into FaultExceptions so they don't fault the communication channel.

     

    Exceptions occuring will be bubbled up to the user in any way, hiding them is not my intent.

     

    Sam

    Thursday, July 19, 2007 2:33 PM
  • Yes, what if the exception is StackException, how can you throw a new exception if you have a stack exception?  I.e. you've run out of stack, how can you push data on the stack in order to throw the exception?  You'll just end up generating an new StackException hiding the other stack exception.
    Thursday, July 19, 2007 2:37 PM
    Moderator
  • Yes, so in that rare case some other exception than FaultException will bubble up, and the service will just close the channel instead of sending the FaultException, so the client will receive a CommunicationsException because of faulted channel.

     

    If I do not rewrap the exceptions to FaultException my client will get a totally useless and meaningless CommunicationsException for any kind of error, without any hint or message what really happened. You really think that is better?

     

    Sam

    Thursday, July 19, 2007 3:04 PM
  • Well, if you're debugging on the server, that StackException won't be seen as a unhandled exception and you'll have to either put a break-point on that line or break-on-all-exceptions (not just unhandled) which can be many before you get to the one you want.

     

    Alternatively you could log the exception an just rethrow, handling (i.e. wrapping them in a new FaultException) specific exceptions that are documented as occurring.  That way you don't hide information that would be otherwise useful, even if rare.

     

    The other issue with catch(Exception ex) is that you're circumventing the exception hierarchy.  If the method above this one in the stack has code to handle a specific exception, catch(Exception) means that code will never see that exception that may otherwise not be a problem for the application--now you've introduced a FaultException where no unhandled exception existed.

    Thursday, July 19, 2007 3:52 PM
    Moderator
  • I agree with Peter here.

    I will add one thing, since this is client/server programming you should have exception handling in place with the client so that if the server crashes/errors out/dies or the connection between client/server is broken. You shouldn't be trying to rig the server to avoid causing exceptions on the client, that's not the job of the server. You either need to find the reason for the exceptions on the server and solve them so they don't occur or you need to realize the event can possible occur and the client needs to be able to handle that case. Even if the way you handle the case is to stop communication and inform the user at the client that something occurred and they need to contact the server. If the client can't communicate with the server than what is the client supposed to do?

    If the server is running into other exceptions while communicating with the client then there is an issue and unless you can handle it and then continue talking to the client, then the server isn't going to be able to continue communication with the client. If the server can't even recover from the exception later, then you're going to have to restart the server before the client can continue communications with the server. Have you been encountering specific exceptions with the server?
    Thursday, July 19, 2007 5:30 PM
  • Peter, Eric,

     

    if you both have read my sample code above you might have noticed that I do not avoid exceptions, I just repack them into a FaultException. So the Exception, any Exception will be propagated to the client.

    The only reason I repack the Exception is to get more and therefore better information about the exception to the client. You see, if I just let any ol' Exception slip through WCF will just close the connection. In this case the client will just get the information that the connection has faulted without any hint why.

     

    So to have just a teenie weenie bit more information at the client in case of an exception to show a meaningful error message to the user (meaningful probably only to the programmer, but hey, thats me, and I like to know such stuff) I need to repack all Exceptions into FaultExceptions.

     

    I really can't imagine why you think I want to hide Exceptions when my question and sample source both show I want to convert them into other exceptions (well, maybe if you only read the title of my post and skipped the posting itself without reading it, but you wouldn't do such a thing, would you?)

     

    Sam

    Thursday, July 19, 2007 8:32 PM
  • Yes, by my point is that when you try to repack a StackException you end up generating a new StackException loosing the context of the other StackException and you won't be able to find out what generated that original StackException; and you're therefore hiding information.  I'm not saying you want to hide exceptions; but that's the end result.

     

    Same with an exception that would otherwise be handled by a method calling this one.  For example: 

    Code Snippet

    void SomeFrameworkMethod()

    {

      try

      {

         SomeUserMethod();

      }

      catch(MySpecificException e)

      {

         // this is a bug this exception is safe to ignore

      }

    }

     

    void SomeUserMethod()

    {

      try

      {

         // Do a bunch of other stuff

      }

      catch(Exception e)

      {

         // try and wrap that up and send it back to the client attempting to add detail

         throw new FaultException(e);

      }

    }

     

    In this case, the SomeFrameworkMethod will now never get the MySpecificException because it was handled in SomeUserMethod and hidden in a new FaultException exception.  You've gone from a situation where everything worked despite MySpecificException being thrown, to a failure (where FaultException is thrown containing a MySpecificException exception).

     

    Thursday, July 19, 2007 8:47 PM
    Moderator
  • Peter, we are talking about a WCF service here - if there is a StackException I will lose the details no matter what I do.

     

    If a StackException comes in this case, at the last stop of a WCF service call, I got two options:

     

    1) just let the StackException pass through (not catch it):

    Since the only Exceptions that can be passed on through SOAP are FaultExceptions, and StackException is not a FaultException this will cause WCF to close the channel. In this case the client gets a CommunicationException since the channel was ungraceful closed. No information about the StackException is going to make it to the client. Nada. Zilch.

     

    2) catch the StackException, throw a FaultException:

    as you said this will cause another StackException, so exactly the same will happen as in case 1)

     

    So whats your point? In case of StackException I got no chance whatsoever to communicate this to the client anyway.

     

    As your example, in direct calling you are right, but client/server WCF is not direct calling, its remoting using a SOAP protocol or something like that, and there is no way to propagate a StackException through this kind of remote call, so your example is very pointless for the kind of problem I asked about. Your example is a whole different kind of beast with no reason to repack any exception, so what you are writing about does not make any sense in my context.

     

    If you rework your example as WCF proxy call you would see it does not work that way when you use WCF for remoting.

     

    Sam

    Thursday, July 19, 2007 9:11 PM
  • StackException is just an example.  But, if you're debugging the server you've gone from being able to just break on an unhandled exception (your case 1) to having to break on all exceptions if you want to get any of the detail of that original exception (your case 2)--for which there could be many.  Believe me, I've been there, it's slightly annoying.

     

    Can you get exception details, like the stack trace, back to the client?

    Thursday, July 19, 2007 10:48 PM
    Moderator
  • Of course I do not show the stack trace and other details to the client - these are implementation details which need/should not be shown to the user.

     

    Really, I don't see what the big deal here is. And more, I don't really see an alternative. You keep saying this might be wrong, but what would be a better way? How would you give the client more information without faulting the communication channel? Heck, or even with faulting the channel - so far I seen no alternative way of handling this.

     

    Sam

     

    Friday, July 20, 2007 6:47 AM
  • I detailed in a previous post that the generally accepted practice is to catch only the exceptions documented as being possibly thrown in the code that you're using.  I don't see what the problem with that is...  That way you don't introduce the problems I detailed.

     

    You certainly don't have to do it that way...

    Friday, July 20, 2007 1:48 PM
    Moderator
  • But you understand what happens in the case of a 'surprise' exception in the case of an WCF Service, don't you?

     

    No exception other than FaultException will make it through the WCF/SOAP communication, therefore if there is any exception that is not explizitely cought I will get no information about this problem at all. Nothing. All I get in case of any other exception than FaultException will be a CommunicationException on the client side.

     

    This is by design of remote calls in WCF. You'd rather throw away any information about unexpected Exceptions, making the client unable to show a meaningful error message?

     

    Sam

    Friday, July 20, 2007 2:16 PM
  •  Sam Jost wrote:

    No exception other than FaultException will make it through the WCF/SOAP communication, therefore if there is any exception that is not explizitely cought I will get no information about this problem at all. Nothing. All I get in case of any other exception than FaultException will be a CommunicationException on the client side.

    I've detailed at least one case where something other than FaultException could be thrown out of your code. The fact is if you catch everything there could be many exceptions that you catch that simply mean your code can't continue.  Since you're attempting to wrap them in another exception all that original exception information is now lost and you can't send it back to the client.  From the client's point of view, yes, it's the same result; but from the server's point of view you've only made debugging harder.  And if you catch only the documented exceptions the client get's the same result, you're still sending back information about the exceptions that you catch and ignoring the ones you don't know may affect your ability to communicate back to the client.

     Sam Jost wrote:

    This is by design of remote calls in WCF. You'd rather throw away any information about unexpected Exceptions, making the client unable to show a meaningful error message?

    I didn't say that, but there's likely nothing you can send back to the client with some exceptions; StackException is the classic example, if you've run out of stack (hence the StackException) you have no stack to throw another exception.  Ergo, it's the same as if you never caught the exception (except that you've made debugging on the server more difficult).  A communications error is another example, is there any point to catching an exception detailing that the client closed the communications channel (i.e. how do you communicate back to the client that it's not listening to you anymore)?

    There's nothing syntactically wrong with catch(Exception); you just shouldn't expect your application to continue at that point.  Since this isn't a last-chance exception handler (you're trying to get information back to the client instead of terminating), it's generally accepted that catch(Exception) in this case is not ideal.  If you never get a StackException, or if there's never a communications error, you're likely fine.  But, if you do end up with one of those two cases and you need to debug it, you'll either have to change to code or go through hoops trying to debug it.  Believe me, I've had to deal with other people's code that does that sort of thing; it's much easier to simply re-write it.

    Friday, July 20, 2007 2:44 PM
    Moderator
  • Ah yes, I think I start to see where our communication problem is:

     

    Have you ever worked with Windows Communication Foundation (WCF)? WCF offers a way to remotely call a function. You set up a communication channel and some classes, and 'magically' when you call a function in a proxy wrapper class on the client, WCF will translate this call with all its parameters into a message, send it to the other end of the communication channel (the server). There the XML message is unpacked, a class of the same interface type as the client is created and a function with the same name in this class will be called.

     

    When this function returns, the returned result will be packed into a XML message and send back to the client. At the client this XML message will be unpacked and the function that was called will return the value that had been sent in the message.

     

    All in all a very convenient way to communicate with a server: after you set up the connection you just call functions, and those return just like a local function would. Very nice.

     

    Until we enter exceptions. You see, the SOAP message used to return the return value to the client is not able to transfer exceptions. It has a way to return errors instead of a return value, but this can't be used to send exceptions.

    So since the server has no way to send back an exception to the client, what will happen if an exception occurs during a call in the server? WCF will just discard the exception and close the communication channel without sending anything back. The Exception and all its details are lost forever, the client only gets a CommunicationException since the communication channel closed.

     

    So even a StackException will not make it to the client. It will just cause the server to close the channel.

     

    It seems to me you don't know this part I just outlined from self experience, and therefore you don't see that no Exception will make it through the channel. None at all. Even if the server hardware burns down the client will just get a communication exception.

     

    do you really understand this part of my context? Because this is important about what I'm doing here.

     

    Sam

     

     

     

    Saturday, July 21, 2007 8:17 AM