The language-puppet
library has been created when I started to learn Haskell. As
a consequence, it uses the dreaded String
type to store all kind of textual
values. It also uses the System.IO
module for performing I/O. I was aware of
the file descriptor leak problem that happens when you use readFile
, so I
chose for the following implementation for the Puppet file
function:
1 2 3 |
|
This should return Just
the content of the first readable file in the
parameter list, or Nothing
if there are none, and should not leak any file
descriptor. Now that I am finalizing the hspuppetmaster
binary, I can use my
library to (try to) compute catalogs on my production systems, using the
standard puppet agent -t --noop
. It turned out that the file
function was
misbehaving. Testing it in GHCi illustrates the problem:
1 2 3 4 |
|
It seems to work fine, except all file contents are empty. This behavior seems to be common knowledge among Haskellers, and is due to the fact that the file descriptor is closed before the output is evaluated. This is pretty horrible (and surprising), and what is even worse is my solution:
1 2 3 4 5 6 |
|
It is a bit longer because of the use of the non-deprecated version of catch
,
and because it explicitly forces evaluation of the output of hGetContents
.
This behavior was extremely surprising to me, and I would like to thank the
people on #haskell
for their help in devising a correct version (mine was
along the lines of !y <- hGetContents
, which worked for my simple examples,
but was certain to fail at some point). This is the only IRC channel I know
of where people are at the same time active, always helpful, and knowledgeable.