La mia prima impressione di readFile
era un compromesso tra la sua convenienza e la possibilità che esso lasciasse i descrittori di file aperti più a lungo del necessario, senza possibilità di chiuderli. Come esperimento ho provato il seguente programma (molto pratico), pensando che potesse soffocare cercando di mantenere un migliaio di descrittori di file aperti:Quando è meglio chiudere esplicitamente gli handle di file?
main = do
mapM_ (\idx -> readIt) [1..1000]
where readIt = do
contents <- readFile "/etc/passwd"
putChar $ head contents
ma in realtà fa un buon lavoro di bonifica descrittori di file; il conto non arriva mai sopra 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
Come sta succedendo? È solo che i valori di contents
stanno ricevendo GC e con essi i descrittori di file non più indirizzati? O esiste un meccanismo separato per la gestione delle risorse dei descrittori di file? Qualunque sia il meccanismo, sembra che funzioni abbastanza bene: come puoi sapere quando è meglio usare hClose
esplicitamente?
Credo che sia solo il GC a causare la chiusura dei descrittori di file. –
In generale, è meglio usare meccanismi che assicurino una gestione deterministica delle risorse (diversa dalla memoria), in Haskell sarebbe 'parentesi'. Non fidarti di GC con i file per qualcosa di più di un semplice caso. La staffa –
ha senso solo con un IO preciso, altrimenti l'effetto può fuoriuscire attraverso i dati pigri. –