2013-09-23 3 views
1

У меня есть внешняя dll, которую я использую в моей программе haskell. В некоторых случаях dll аварийно завершает работу.Haskell/FFI: как обращаться с внешними сбоями dll

Упрощенный: сначала мне нужно отправить в dll с помощью MethodA некоторые параметры, а затем вызвать MethodB для выполнения некоторых вычислений по этим параметрам. Если бы я не дал достаточно параметров, то MethodB разрушит всю dll. В этом случае приложение Haskell также выходит из строя.

Есть ли способ справиться с этим? К сожалению, исключений, исключенных из dll, нет.

В ghci я получаю следующее сообщение: ERROR в InitNumericalSystem :: initializeSystem. JuncLabel.

Я пытался использовать «catchAny, но это не помогло c_run мой внешний метод длл, который принимает 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 

EDIT: Я пытался также с withAsync, и не повезло tryAny :: IO а -> IO (Либо SomeException а) действие tryAny = действие withAsync 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 

ответ

3

при вызове функции в DLL из Haskell, нет сети безопасности, которая предотвращает DLL от баловаться с вами адресное пространство процесса , Я вижу три варианта:

  • Если у DLL есть нормальный API, будет возможно определить, будет ли вызов успешным, прежде чем запутаться. Вы могли бы даже обеспечить «правильное использование», выразив эти условия в системе типов Haskell. Таким образом, когда ваш код Haskell компилируется, у вас также не будет сбоев во время выполнения из библиотеки DLL.
  • Нередко библиотеки DLL могут предлагать функцию для проверки того, вызвал ли последний вызов ошибку. Возможно, вы хотите изучить это направление.
  • Если «сбой» означает, что вызов вызывает ошибку сегментации или что-то подобное, Haskell/GHC/время выполнения может не работать. Вы можете изолировать проблему, выполнив вызовы в DLL из отдельного процесса, созданного из основного процесса. Это, очевидно, вводит стоимость производительности для нереста дочерних процессов и передачи данных.
Смежные вопросы