Skip to content

`readFile` leaks file descriptors in the presence of asynchronous exceptions

Summary

System.IO.readFile leaks file descriptors in the presence of asynchronous exceptions.

Steps to reproduce

Run

module Main where

import Control.Concurrent
import Data.Foldable
import System.IO

main :: IO ()
main =
  do
    for_ [1..300] go
    -- at this point, execute `ls -l "/proc/$(pidof readfile-test-exe)/fd"`
    -- every listing of `test.txt` constitutes a leaked file descriptor
    getLine
    pure ()

go :: Integer -> IO ()
go n =
  do
    id <- forkIO (readFile "test.txt" >>= putStr)
    threadDelay 1
    killThread id
    pure ()

(https://gitlab.com/rdnz/readfile-test/-/blob/system-io/app/Main.hs).

Execute ls -l "/proc/$(pidof readfile-test-exe)/fd" in a new terminal.

Expected behavior

ls -l "/proc/$(pidof readfile-test-exe)/fd" should not list any test.txt.

Environment

  • GHC version used: 8.8.4
  • Operating System: NixOS 20.03.2843.14006b724f3
  • Kernel Version: 5.4.60
  • OS Type: 64-bit
  • Processors: 2 × Intel® Core™2 Duo CPU P8700 @ 2.53GHz
  • Memory: 3.6 GiB of RAM
Edited by Philipp
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information