Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to track down the type of uncaught exception?

Coming from JVM languages which output a mammoth stack-trace whenever an exception is uncaught, I feel frustrated when I see something like connect: does not exist (Connection refused) and nothing else in the output of my program and then it closes. I understand that some exception got raised and not caught. I even expected an exception to occur, since I tried to connect to an offline server. So all I need is just a way to handle this exception, but what I don't understand is how I am supposed to find out what type of that exception is to do that.

What I usually did to this day was just google for the specific message and dig thru all the mail-list archives or source files in search for information, but that can't be the right approach. So, my question is as in the title:

How to track down the type of uncaught exception?

like image 906
Nikita Volkov Avatar asked Oct 24 '13 11:10

Nikita Volkov


People also ask

How do you handle the uncaught exceptions?

It allow us to handle the exception use the keywords like try, catch, finally, throw, and throws. When an uncaught exception occurs, the JVM calls a special private method known dispatchUncaughtException( ), on the Thread class in which the exception occurs and terminates the thread.

What is unhandled exception type?

An unhandled exception is an error in a computer program or application when the code has no appropriate handling exceptions. Learn about the definition and examples of unhandled exceptions, and explore programming and exception handlers. Updated: 01/04/2022.

Which of the following is the easiest way to track all unhandled errors?

An ExceptionFilterAttribute is used to collect unhandled exceptions. You can register it as a global filter, and it will function as a global exception handler. Another option is to use a custom middleware designed to do nothing but catch unhandled exceptions.

What are uncaught exceptions?

CWE 248-Uncaught Exception occurs when an exception is not caught by a programming construct or by the programmer, it results in an uncaught exception. In Java, for example, this would be an unhandled exception that would terminate the program.


4 Answers

You can use typeOf to print the type of the exception:

import Data.Typeable
import Control.Exception
import System.IO.Error

blackbox1 :: IO ()
blackbox1 = throw $ mkIOError doesNotExistErrorType "blackbox1" Nothing (Just "evil")

blackbox2 :: IO ()
blackbox2 = throw DivideByZero

traceExceptionName :: IO () -> IO ()
traceExceptionName act = act `catch` \(SomeException e) -> do
  let rep = typeOf e
      tyCon = typeRepTyCon rep
  putStrLn $ "## Exception: Type " ++ show rep ++ " from module " ++ tyConModule tyCon ++ " from package " ++ tyConPackage tyCon
--  throw e -- Rethrow exception.

main :: IO ()
main = do
  traceExceptionName blackbox1
  traceExceptionName blackbox2

Example output

$ runhaskell ./main.hs            
## Exception: Type IOException from module GHC.IO.Exception from package base
## Exception: Type ArithException from module GHC.Exception from package base
like image 73
bennofs Avatar answered Nov 15 '22 04:11

bennofs


This is genuinely one of the very worst parts of Haskell—it's very hard to get stack traces out of it.

The most direct way is to compile the program for profiling then call it with the RTS option

myprog +RTS -xc -RTS

which will dump a stack trace, though I've heard it's a little buggy and may not work well. This is the example from the documentation

*** Exception raised (reporting due to +RTS -xc), stack trace:
  GHC.List.CAF
  --> evaluated by: Main.polynomial.table_search,
  called from Main.polynomial.theta_index,
  called from Main.polynomial,
  called from Main.zonal_pressure,
  called from Main.make_pressure.p,
  called from Main.make_pressure,
  called from Main.compute_initial_state.p,
  called from Main.compute_initial_state,
  called from Main.CAF

I've gone as far as grepping the source for particular error strings, though, when -xc didn't provide enough extra information.

If you've got an uncatchable exception rising up through a particular library and you'd like to handle it in a more pure way, you may like to use the functions in the spoon package to convert it to a pure Maybe result. From there you can re-raise it via your own exceptions. That may make the error easier to handle as well.

like image 26
J. Abrahamson Avatar answered Nov 15 '22 02:11

J. Abrahamson


If all you need is the type, why not use typeOf? All exceptions must be instances of Typeable.

like image 26
Michael Snoyman Avatar answered Nov 15 '22 04:11

Michael Snoyman


I like J. Abrahamson's answer, but if that fails or you want an alternative... I temporarily write a handler that catches "all" exceptions, only to print out the name of the exception. Once I have that, I modify the exception handler to deal with only the exception(s) I can handle.

But read the warning about "Catching all exceptions"


EDIT: Here's some sample code:

catch XXXXXXX
  (\e -> do
     let err = show (e :: SomeException)
     hPutStr stderr ("Warning: " ++ err)
     return ())
like image 1
mhwombat Avatar answered Nov 15 '22 02:11

mhwombat