ndmitchell / shake

Shake build system
http://shakebuild.com
Other
772 stars 118 forks source link

How to install custom exception handler for actions #358

Open ezyang opened 8 years ago

ezyang commented 8 years ago

Use case: I'm calling the ghc API directly, and some IO actions I run will raise exceptions. I would like to use GHC.printException to render these exceptions (the default Show instance doesn't include such niceties as pretty printing or line numbers), and then have Shake abort (or attempt to keep going, if it was configured to do so.)

Here are a few non-solutions:

  1. actionOnException. I don't get the exception, that's no good.
  2. Install the exception handler myself. First, I can't scope the handler over an entire action. Secondly, I do want to emit an exception to Shake proper, but I don't want Shake to go and reemit the error AGAIN.

So what should I do?

ndmitchell commented 8 years ago

Having actionOnException get the exception isn't terrible - I just don't want people to be able to ignore exceptions, so no catch/handle.

If you could specify a custom pretty printer for the exception, would that be enough? In general, Shake just bubbles the exception up to the top, so the only time Shake really prints the exception itself is with staunch mode.

ezyang commented 8 years ago

I figured out the problem: Shake bubbles the exception up, but it CHANGES what the type of the exception is. Case in point:

{-# LANGUAGE NondecreasingIndentation #-}
{-# LANGUAGE ScopedTypeVariables #-}

import Development.Shake
import Control.Exception
import GHC.Conc

main = do
    setUncaughtExceptionHandler $ \e -> putStrLn "caught it 2"
    handle (\(e :: ErrorCall) -> putStrLn "caught it 1")
           (shakeArgs shakeOptions $ action $ error "boom")

Nothing is caught, but if you change ErrorCall to SomeException the handler does catch it.

(and it would be quite helpful to have the custom error handler in staunch mode too...)

ndmitchell commented 8 years ago

Shake always changes the exception to be of type ShakeException, which has a member shakeExceptionInner if you do need the inner exception.

Agreed, for Staunch something will be needed, although not sure what - see also https://github.com/ndmitchell/shake/issues/287 which is in the same area.