Skip to content

GHC's runtime never terminates unused worker threads

When concurrently calling safe FFI functions, worker OS threads are created. These threads then never quit.

The following toy program creates 30k OS threads (which is fine because that's exactly what it asks for) which are then never "garbage collected": 30k threads and over 230g of VM are hanging around until the program exits.

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Control.Concurrent
import Control.Monad
import Foreign.C.Types
import System.Mem

foreign import ccall safe sleep :: CUInt -> IO ()

main = do
    replicateM_ 30000 $ forkIO $ sleep 2
    getLine
    -- do other stuff

P.S. Of course I should simply use threadDelay in this case. The real program performs up to a few hundred concurrent fdatasync calls.

Trac metadata
Trac field Value
Version 6.12.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Runtime System
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information