Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it better to explicitly close file handles?

Tags:

haskell

My first impression of readFile was of a tradeoff between its convenience and the possibility of it leaving file descriptors open longer than needed, with no way to close them. As an experiment I tried the following (highly practical) program, thinking it might choke by trying to maintain a thousand open file descriptors:

main = do
  mapM_ (\idx -> readIt) [1..1000]
  where readIt = do
          contents <- readFile "/etc/passwd"
          putChar $ head contents

But it actually does a pretty good job of reclaiming file descriptors; the count never gets above around 70:

open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 5
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 6
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 7
...
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 65
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 66
close(3)                                = 0
close(4)                                = 0
close(5)                                = 0
...
close(54)                               = 0
close(55)                               = 0
close(56)                               = 0
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 3
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4

How is this happening? Is it just that the values of contents are getting GC'd, and with them the no-longer-referenced file descriptors? Or is there some separate mechanism for managing file descriptor resources? Whatever the mechanism is, it seems to be working pretty well - how can you know when it's best to use hClose explicitly?

like image 977
gcbenison Avatar asked May 29 '12 21:05

gcbenison


People also ask

Why it is important to close a file and how do you close it?

Because files are limited resources managed by the operating system, making sure files are closed after use will protect against hard-to-debug issues like running out of file handles or experiencing corrupted data.

When should I close a file in Python?

Though Python automatically closes a file if the reference object of the file is allocated to another file, it is a standard practice to close an opened file as a closed file reduces the risk of being unwarrantedly modified or read.

What is the purpose of closing a file?

The act of closing the file (actually, the stream) ends the association; the transaction with the file system is terminated, and input/output may no longer be performed on the stream. The stream function close may be used to close a file; the functions described below may be used to open them.

When should you close a file in C?

A file needs to be closed after a read or write operation to release the memory allocated by the program. In C, a file is closed using the fclose() function. This returns 0 on success and EOF in the case of a failure. An EOF is defined in the library called stdio.


2 Answers

It is better to explicitly close resources yourself, only when you have some low level resource constraint that you can actually enforce manually.

The cases to consider:

  • resources aquired via lazy IO: must use the GC to free the resource
  • strict IO: can close manually once input is read; or use a bracketing combinator (e.g. finally or bracket)
  • incremental IO (conduits, iteratees): let the framework close it for you.
like image 175
Don Stewart Avatar answered Dec 07 '22 00:12

Don Stewart


The Haddock docs for System.IO have this to say:

GHC note: a Handle will be automatically closed when the garbage collector detects that it has become unreferenced by the program. However, relying on this behaviour is not generally recommended: the garbage collector is unpredictable. If possible, use an explicit hClose to close Handles when they are no longer required. GHC does not currently attempt to free up file descriptors when they have run out, it is your responsibility to ensure that this doesn't happen.

like image 38
Nathan Kleyn Avatar answered Dec 06 '22 22:12

Nathan Kleyn