elaRosca
elaRosca

Reputation: 3153

Segmentation fault when running hs_init(0, 0) for ffi

I am trying to call Haskell functions from python. I have the following make file:

GHC=ghc
GHC_RUNTIME_LINKER_FLAG=-lHSrts-ghc7.4.1

libffi-example.so: Example.o wrapper.o
    $(GHC) -o $@ -shared -dynamic -fPIC $^ $(GHC_RUNTIME_LINKER_FLAG)

Example_stub.h Example.o: Example.hs
    $(GHC) -c -dynamic -fPIC Example.hs

wrapper.o: wrapper.c Example_stub.h
    $(GHC) -c -dynamic -fPIC wrapper.c

clean:
    rm -f *.hi *.o *_stub.[ch]

clean-all:
    rm -f *.hi *.o *_stub.[ch] *.so


# Runs the example Python program
example: libffi-example.so
    python program.py

The only thing wrapper.c does it creating wrappers for hs_init by calling hs_init(0,0);. The wrapper is called example_init

I get a segmentation fault when running make example, in example_init (ie when calling hs_init(0,0)).

Can someone tell me why this is and/or how to fix it?

Thanks!

Upvotes: 2

Views: 452

Answers (1)

Daniel Fischer
Daniel Fischer

Reputation: 183888

It ought to work:

"Moreover, hs_init() may be called with NULL for both argc and argv, signalling the absence of command line arguments."

It seems to be a bug in ghc-7.2.1 to ghc-7.4.1:

RFib.hs:

{-# LANGUAGE ForeignFunctionInterface #-}
module RFib where

fib :: Int -> Int
fib n
    | n >= 0    = go 0 1 n
    | even n    = -go 0 1 (-n)
    | otherwise = go 0 1 (-n)
      where
        go a _ 0 = a
        go a b k = go b (a+b) (k-1)

foreign export ccall "rfib" fib :: Int -> Int

rfib.c:

#include <stdio.h>
#include <HsFFI.h>

int rfib(int);

int main(void) {
    hs_init(0,0);
    printf("%d\n", rfib(35));
    hs_exit();
    return 0;
}

Compile and run:

$ rm rfib.o RFib.hi RFib.o a.out
$ ghc-7.0.2 -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
9227465
$ rm rfib.o RFib.hi RFib.o a.out
$ ghc-7.0.4 -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
9227465
$ rm rfib.o RFib.hi RFib.o a.out
$ ghc-7.2.1 -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
Speicherzugriffsfehler
$ rm rfib.o RFib.hi RFib.o a.out
$ ghc-7.2.2 -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
Speicherzugriffsfehler
$ rm rfib.o RFib.hi RFib.o a.out
$ ghc-7.4.1 -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
Speicherzugriffsfehler
$ rm rfib.o RFib.hi RFib.o a.out
$ ghc-7.4.2 -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
9227465
$ rm rfib.o RFib.hi RFib.o a.out
$ ghc -O2 -Wall -no-hs-main RFib.hs rfib.c && ./a.out
[1 of 1] Compiling RFib             ( RFib.hs, RFib.o )
Linking a.out ...
9227465

Changing two lines in rfib.c:

int main(int argc, char *argv[]) {
    hs_init(&argc,&argv);

it works with all versions (>= 7.0 that I have installed).

So to fix it

  • pass &argc and &argv
  • upgrade GHC

are the two most obvious ways.

Upvotes: 2

Related Questions