Opened 10 months ago

Last modified 9 months ago

#15933 new bug

Wrong size for int for callbacks into Haskell from foreign code

Reported by: iliastsi Owned by:
Priority: normal Milestone:
Component: Compiler (FFI) Version: 8.4.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

The following code produces different results on amd64 (64-bit little endian) and s390x (64-bit big endian).

foo.h:

typedef void(*hs_callback)(int x);
extern void function_in_c(hs_callback cb);

foo.c:

#include "foo.h"

void function_in_c(hs_callback cb)
{
    int x = 10;
    cb(x);
}

Foo.hs:

module Main(main) where

import Foreign
import Foreign.C

type HsCallback = CInt -> IO ()

foreign import ccall "foo.h function_in_c"
  functionInC :: FunPtr HsCallback -> IO ()

foreign import ccall "wrapper"
  wrap :: HsCallback -> IO (FunPtr HsCallback)

main = do
  f <- wrap $ \x -> print x
  functionInC f
  freeHaskellFunPtr f

On amd64 the output is 10, but on s390x is 0. On both machines, sizeOf (undefined :: CInt) == sizeof(int) == 4. When changing HsCallback to:

type HsCallback = Int -> IO ()

both produce the same, correct result, but the above seems wrong, as sizeOf (undefined :: Int) == 8.

This has been reproduced with both ghc-8.4 and ghc-8.2, and causes dbus to fail to build on s390x (https://github.com/rblaze/haskell-dbus/issues/26), as it relies on libxml-sax which contains the above (simplified) code.

Change History (1)

comment:1 Changed 9 months ago by bgamari

Milestone: 8.6.3

Ticket retargeted after milestone closed

Note: See TracTickets for help on using tickets.