Вопрос

I have an external dll that I'm using in my haskell program. In some particular cases the dll crashes.

Simplified: first I need to send to dll with MethodA some parameters and then call MethodB to do some calculations on those parameters. If I didn't give enough parameters then MethodB will crash the whole dll. In this case my Haskell application crashes too.

Is there a way to handle this? Unfortunately there are no exceptions thrown from the dll.

In ghci I'm getting following message: ERROR in InitNumericalSystem::initializeSystem. JuncLabel.

I have tried to use "catchAny but that didn't help. c_run is my external dll method which takes 4 input parameters:

catchAny :: IO a -> (SomeException -> IO a) -> IO a
catchAny = Control.Exception.catch

main :: IO ()
main = do
  let timeTot = []::[CDouble]
      timeNow = []::[CDouble]
      runType = 2::CInt
  timeTotPtr <- newArray timeTot
  timeNowPtr <- newArray timeNow
  result <- (catchAny $ c_run timeTotPtr runType timeNowPtr 0) $ \e -> do
    putStrLn $ "Got an exception: " ++ show e
    putStrLn "Returning dummy value of -1"
    return (-1)
  free timeTotPtr 
  free timeNowPtr 
  print result

EDIT: I have tried also with withAsync, and no luck tryAny :: IO a -> IO (Either SomeException a) tryAny action = withAsync action waitCatch

catchAny :: IO a -> (SomeException -> IO a) -> IO a
catchAny action onE = tryAny action >>= either onE return

try2 :: IO ()
try2 = do
      let timeTot = []::[CDouble]
          timeNow = []::[CDouble]
          runType = 2::CInt
      timeTotPtr <- newArray timeTot
      timeNowPtr <- newArray timeNow
      putStrLn $ "c_run going to call c_run.."
      result <- catchAny (c_run timeTotPtr runType timeNowPtr 0) (const $ return (-1))
      free timeTotPtr
      free timeNowPtr
      putStrLn $ "Result: " ++ show result
Это было полезно?

Решение

If you call functions in a DLL from Haskell, there is no safety net which prevents the DLL from messing with you process' address space. I see three options here:

  • If the DLL has a sane API, it will be possible to determine if the call will succeed before messing up. You could even enforce "proper use" by expressing these conditions in Haskell's type system. This way, when your Haskell code compiles, you won't have runtime crashes from the DLL as well.
  • It is not uncommon for DLLs to offer a function to check if the last call caused an error. Maybe you want to explore this direction.
  • If by "crashing" you mean that the call causes an segmentation fault or the like, there's not much Haskell / GHC / the runtime can do about it. You might isolate the problem by doing the calls to the DLL from a separate process, spawned from your main process. This obviously introduces a performance cost for spawning the child processes and passing the data around.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top