Home Two ways System.IO.withFile has messed with me
Post
Cancel

Two ways System.IO.withFile has messed with me

Gotcha #1: handles getting closed

This is not really withFile’s fault, but:

1
2
3
4
5
6
7
8
9
10
11
12
13
main = do
  withFile "/tmp/foo.txt" WriteMode $ \h -> do
    (_, _, _, p1) <- createProcess ((proc "hello" []) {
      std_out = UseHandle h
      , std_err = UseHandle h
      })
    _ <- waitForProcess p1

    (_, _, _, p2) <- createProcess ((proc "hello" []) {
      std_out = UseHandle h
      , std_err = UseHandle h
      })
    _ <- waitForProcess p2

This fails with the following:

1
my-exe: /tmp/foo.txt: withFile: invalid argument (Bad file descriptor)

Can you guess why? It’s because the first createProcess call causes the handle to be closed. Then the “bad file descriptor” exception is thrown on the second createProcess call.

Gotcha #2: it catches unrelated exceptions

Now let’s say we trigger an unrelated exception within a withFile, say by trying to start a process that doesn’t exist.

1
2
3
4
5
main :: IO ()
main = do
  withFile "/tmp/foo.txt" WriteMode $ \h -> do
    _ <- readCreateProcess (proc "nonexistent-exe" [])
    putStrLn "Done!"

This fails with

1
withfile-repro-exe: /tmp/foo.txt: withFile: does not exist (No such file or directory)

Extremely confusing. Makes it sounds like it failed to open the log file.

This post is licensed under CC BY 4.0 by the author.