Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,323
    • Issues 4,323
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 376
    • Merge Requests 376
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #8648

Closed
Open
Opened Jan 04, 2014 by edsko@edsko.net@trac-edsko

Initialization of C statics broken in threaded runtime

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).

Trac metadata
Trac field Value
Version 7.7
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Runtime System
Test case
Differential revisions
BlockedBy
Related
Blocking
CC simonmar
Operating system
Architecture
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#8648