[GHC] #8648: Initialization of C statics broken in threaded runtime

GHC ghc-devs at haskell.org
Sat Jan 4 16:14:15 UTC 2014


#8648: Initialization of C statics broken in threaded runtime
------------------------------------+-------------------------------------
       Reporter:  edsko             |             Owner:  simonmar
           Type:  bug               |            Status:  new
       Priority:  normal            |         Milestone:
      Component:  Runtime System    |           Version:  7.7
       Keywords:                    |  Operating System:  Unknown/Multiple
   Architecture:  Unknown/Multiple  |   Type of failure:  None/Unknown
     Difficulty:  Unknown           |         Test Case:
     Blocked By:                    |          Blocking:
Related Tickets:                    |
------------------------------------+-------------------------------------
 Consider a tiny package `static-value`, consisting of one Haskell file

 {{{
 foreign import ccall unsafe "returnStaticValue" c_returnStaticValue :: IO
 CInt

 printStaticValue :: IO ()
 printStaticValue = print =<< c_returnStaticValue
 }}}

 and one corresponding C file

 {{{
 static int theStaticValue = 0;

 int returnStaticValue() {
   // Modify the static so the C compiler doesn't optimize it away
   return theStaticValue++;
 }
 }}}

 (test case is attached). If we call `printStaticValue` using the GHC API:

 {{{
 runGhc (Just libdir) $ do
     flags0 <- getSessionDynFlags
     void $ setSessionDynFlags flags0 {
         hscTarget = HscInterpreted
       , ghcLink   = LinkInMemory
       , ghcMode   = CompManager
       }

     setContext $ [ IIDecl $ simpleImportDecl $ mkModuleName "StaticValue"
 ]
     _ <- runStmt "StaticValue.printStaticValue" RunToCompletion
 }}}

 then we see "0", as expected. However, if we compile this code using the
 threaded runtime, and we wrap the above code in a call to either `forkIO`
 or `forkOS`, then we see a different value printed (-907777, whatever that
 value is).

 Some notes:

 * I have been unable to reproduce this bug without using GHC as API; in
 particular, calling `printStaticValue` directly, wrapped in `forkIO` or
 `forkOS` or not, always works as expected.
 * If I change the initialization value of `staticValue` from 0 to anything
 else (say, 1234), we always get the right answer, never the uninitialized
 value. Presumably this is because non-zero values require some explicit
 code to be run (and it does get run), while a zero value gets initialized
 differently (and apparently, that's where the bug is).
 * I have reproduced this bug in both ghc 7.4 and 7.7.20131227.

 This ticket is the result of tracking down a problem with calling
 `createProcess` from within the GHC API, which would cause the parent
 process to stall. As it turns out, `runProcess.c` (from the `process`
 library) declares a `static long max_fd = 0`, and in
 `runInteractiveProcess` checks for this value to be 0, and if it is, does
 a syscall to figure out what the maximum FD is. But since this static does
 not get initialized properly (the bug reported in this ticket), it gets
 left at its (random? but always the same) value (281474975802879), so that
 the child process proceeds to close rather too many file descriptors (if
 close_fds was set to True) and the parent stalls. Indeed, changing the
 initialization to `static long max_fd = -1` (and adjusting the later check
 for zero accordingly) fixes this (so this is a viable workaround in
 `process` if we cannot track down the bug in GHC).

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8648>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list