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?
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.
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.
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.
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.
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
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.
If all you need is the type, why not use typeOf? All exceptions must be instances of Typeable
.
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 ())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With