Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching C++ FFI Exception fails in Haskell

Tags:

c++

haskell

cabal

When using FFI to C++ in Haskell, I am able to properly catch exceptions when running the function in cabal repl, but when running with cabal run, the exception is not caught.

A simple cabal project that exhibits the problem is included below:

exception.cabal:

name:                exception
version:             0.1.0.0
build-type:          Simple
cabal-version:       >=1.10
executable exception
  main-is:             Main.hs
  c-sources: main.cxx
  build-depends:       base >=4.7 && <4.8
  default-language:    Haskell2010
  extra-libraries:     stdc++

main.cxx:

# include <exception>
# include <stdexcept>

extern "C" int hs_exception() try
{
  throw std::logic_error("THIS FAILS!");
} catch(...) {
}

and

Main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Foreign.C.Types (CInt(..))


main = print c_hs_exception

foreign import ccall unsafe "hs_exception"
    c_hs_exception :: CInt

Working from the REPL (i.e GHCI):

cabal repl
*Main> main
0

But failing when compiled with GHC and ran:

cabal run
libc++abi.dylib: terminating with uncaught exception of type std::logic_error: THIS FAILS!
[1]    12781 abort      cabal run

My compilers:

➜ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
➜ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.3
like image 360
jek Avatar asked Aug 22 '14 07:08

jek


1 Answers

This is Mac-specific, and was reported as GHC bug 11829. The fix is to pass the flag -lto_library (LTO = link time optimization) to Clang's linker. This can be done with an executable section of a .cabal file like so:

executable myprog
  ...
  if os(darwin)
    ld-options: -lto_library

Or the flag -optl-lto_library if calling ghc directly.

Note that this will incorrectly recommend you write extra-libraries: to_library instead, which will not work.

like image 135
Onyxite Avatar answered Sep 18 '22 18:09

Onyxite