tags:

views:

90

answers:

2

I am using GHC 6.12.1, in Ubuntu 10.04

When I try to use the FFI syntax for static storage, only modules running in interpreted mode (ie GHCI) work properly. Compiled modules have invalid pointers, and do not work. I'd like to know whether anybody can reproduce the problem, whether this an error in my code or GHC, and (if the latter) whether it's a known issue.

I'm using sys_siglist because it's present in a standard library on my system, but I don't believe the actual storage used matters (I discovered this while writing a binding to libidn). If it helps, sys_siglist is defined in <signal.h> as:

extern __const char *__const sys_siglist[_NSIG];

I thought this type might be the problem, so I also tried wrapping it in a plain C procedure:

#include<stdio.h>
const char **test_ffi_import()
{
    printf("C think sys_siglist = %X\n", sys_siglist);
    return sys_siglist;
}

However, importing that doesn't change the result, and the printf() call prints the same pointer value as show siglist_a.

My suspicion is that it's something to do with static and dynamic library loading.

Update: somebody in #haskell suggested this might be 64-bit specific; if anybody tries to reproduce it, can you mention your architecture and whether it worked in a comment?

Code as follows:

-- A.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module A where
import Foreign
import Foreign.C

foreign import ccall "&sys_siglist"
    siglist_a :: Ptr CString

--

-- B.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module B where
import Foreign
import Foreign.C

foreign import ccall "&sys_siglist"
    siglist_b :: Ptr CString

--

-- Main.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign
import Foreign.C
import A
import B

foreign import ccall "&sys_siglist"
    siglist_main :: Ptr CString

main = do
    putStrLn $ "siglist_a    = " ++ show siglist_a
    putStrLn $ "siglist_b    = " ++ show siglist_b
    putStrLn $ "siglist_main = " ++ show siglist_main

    peekSiglist "a   " siglist_a
    peekSiglist "b   " siglist_b
    peekSiglist "main" siglist_main

peekSiglist name siglist = do
    ptr <- peekElemOff siglist 2
    str <- maybePeek peekCString ptr
    putStrLn $ "siglist_" ++ name ++ "[2] = " ++ show str

I would expect something like this output, where all pointer values identical and valid:

$ runhaskell Main.hs 
siglist_a    = 0x00007f53a948fe00
siglist_b    = 0x00007f53a948fe00
siglist_main = 0x00007f53a948fe00
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

However, if I compile A.hs (with ghc -c A.hs), then the output changes to:

$ runhaskell Main.hs 
siglist_a    = 0x0000000040378918
siglist_b    = 0x00007fe7c029ce00
siglist_main = 0x00007fe7c029ce00
siglist_a   [2] = Nothing
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"
+1  A: 

I can not reproduce this with either 6.10.4 or 6.12.1 on Linux x86. (please edit your question to confirm the architecture you see this on is x86-64)

[tommd@Mavlo Test]$ ghc-6.12.1 --make irc.hs
[1 of 3] Compiling B                ( B.hs, B.o )
[2 of 3] Compiling A                ( A.hs, A.o )
[3 of 3] Compiling Main             ( irc.hs, irc.o )
Linking irc ...
[tommd@Mavlo Test]$ ./irc
siglist_a    = 0x080ab4c0
siglist_b    = 0x080ab4c0
siglist_main = 0x080ab4c0
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"
[tommd@Mavlo Test]$ ghc-6.10.4 irc.hs --make
[1 of 3] Compiling A                ( A.hs, A.o )
[2 of 3] Compiling B                ( B.hs, B.o )
[3 of 3] Compiling Main             ( irc.hs, irc.o )
Linking irc ...
[tommd@Mavlo Test]$ ./irc
siglist_a    = 0x0809ec80
siglist_b    = 0x0809ec80
siglist_main = 0x0809ec80
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"
TomMD
If *all* of the code is compiled, it also works on my system; the error only occurs when a compiled module is loaded into GHCI.
John Millikin
Yeah, that works fine for me too.
TomMD
+1  A: 

You are encountering this bug. Compile your code with -fPIC to workaround it.

Simon Marlow