Skip to content

GHCi segfaults on Windows when compiling C code using extern-declared variable

Phyx- and I noticed that bindings-GLFW unpredictably segfaults when running this simple program in interpreted code:

module Main where

import qualified Graphics.UI.GLFW as G

main :: IO ()
main = do
  successfulInit <- G.init
  return ()

Phyx- suspected that it had something to do with the extern-declared variables used in the GLFW library itself. To avoid requiring a dependency on GLFW, I boiled the issue down to a small, reproducible example with no dependencies, located at https://github.com/RyanGlScott/extern-bug. I will reproduce the code below:

// foo.h
#ifndef FOO_H
#define FOO_H

extern int foo;

void bar(void);
void baz(void);

#endif
// bar.c
#include "foo.h"

int foo = 0;

void bar(void) {
    foo = 1;

    baz();
}
// baz.c
#include "foo.h"
#include <stdio.h>

void baz(void) {
    printf("The value of foo is %d\n", foo); // Segfaults on this line
    fflush(stdout);
}
-- ExternBug.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module ExternBug (bar) where

{-# INCLUDE foo.h #-}

foreign import ccall "bar"
  bar :: IO ()

While I've managed to reproduce this bug sporadically with GHC 7.10.3, it happens far more reliably with GHC 8.0. Here is what I did to trigger the segfault:

  1. Run ghc bar.c baz.c ExternBug.hs
  2. Run ghci bar.o baz.o ExternBug.hs
  3. Invoke bar

I'm not sure what's happening, but there seem to be four important ingredients here:

  1. This needs to be run in interpreted code. Compiled code does not have this issue.
  2. The C sources need to be compiled to object code using GHC. (For example, if you link the MSYS2-provided mingw-w64-x86_64-glfw DLL, it will work correctly.)
  3. There needs to be an extern-declared variable. (For example, uncommenting the lines mentioning the foo variable will make the issue go away.)
  4. There needs to be at least two .c files. One file needs to assign a value to the extern-declared variable, and the other file needs to use the value. (For example, if you put the definitions of bar and baz in the same file, the bug doesn't occur.)
Trac metadata
Trac field Value
Version 8.0.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component GHCi
Test case
Differential revisions
BlockedBy
Related
Blocking
CC Phyx-
Operating system
Architecture Unknown/Multiple
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information