Haskell / FFI:如何处理外部DLL崩溃

时间:2013-09-23 07:51:58

标签: haskell dll crash ffi

我有一个外部dll,我正在我的haskell程序中使用。在某些特殊情况下,dll会崩溃。

简化:首先我需要使用MethodA向dll发送一些参数,然后调用MethodB对这些参数进行一些计算。如果我没有提供足够的参数,那么MethodB将崩溃整个dll。在这种情况下,我的Haskell应用程序也崩溃了。

有办法解决这个问题吗?不幸的是,dll没有例外。

在ghci中我收到以下消息:InitNumericalSystem :: initializeSystem中的ERROR。 JuncLabel。

我试过使用“catchAny但没有帮助.c_run是我的外部dll方法,需要4个输入参数:

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
编辑:我也尝试过withAsync,没有运气     tryAny :: IO a - &gt; IO(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

1 个答案:

答案 0 :(得分:3)

如果从Haskell调用DLL中的函数,则没有安全网可以防止DLL弄乱你处理的地址空间。我在这里看到三个选项:

  • 如果DLL具有合理的API,则可以在搞乱之前确定调用是否成功。您甚至可以通过在Haskell的类型系统中表达这些条件来强制执行“正确使用”。这样,当您的Haskell代码编译时,您也不会从DLL中发生运行时崩溃。
  • DLL提供检查上次调用是否导致错误的函数的情况并不少见。也许你想探索这个方向。
  • 如果“崩溃”意味着调用会导致分段错误等,那么Haskell / GHC /运行时就无法做到这一点。您可以通过从主进程生成的单独进程调用DLL来隔离问题。这显然会产生产生子进程和传递数据的性能成本。