Always use the safe open() call
authorSimon Marlow <marlowsd@gmail.com>
Mon, 11 Dec 2017 17:56:09 +0000 (12:56 -0500)
committerBen Gamari <ben@smart-cactus.org>
Mon, 11 Dec 2017 19:58:20 +0000 (14:58 -0500)
open() can sometimes take a long time, for example on NFS or FUSE
filesystems.  We recently had a case where open() was taking multiple
seconds to return for a (presumably overloaded) FUSE filesystem, which
blocked GC and caused severe issues.

Test Plan: validate

Reviewers: niteria, bgamari, nh2, hvr, erikd

Reviewed By: bgamari

Subscribers: rwbarton, thomie, carter

GHC Trac Issues: #13296

Differential Revision: https://phabricator.haskell.org/D4239

(cherry picked from commit cafe98345cb5d4b11f2059d60d2f20e976ef4f2a)

libraries/base/GHC/IO/FD.hs

index a7a34c1..4a4f063 100644 (file)
@@ -179,14 +179,10 @@ openFile filepath iomode non_blocking =
              | otherwise    = oflags2
     in do
 
-    -- the old implementation had a complicated series of three opens,
-    -- which is perhaps because we have to be careful not to open
-    -- directories.  However, the man pages I've read say that open()
-    -- always returns EISDIR if the file is a directory and was opened
-    -- for writing, so I think we're ok with a single open() here...
-    fd <- throwErrnoIfMinus1Retry "openFile"
-                (if non_blocking then c_open      f oflags 0o666
-                                 else c_safe_open f oflags 0o666)
+    -- NB. always use a safe open(), because we don't know whether open()
+    -- will be fast or not.  It can be slow on NFS and FUSE filesystems,
+    -- for example.
+    fd <- throwErrnoIfMinus1Retry "openFile" $ c_safe_open f oflags 0o666
 
     (fD,fd_type) <- mkFD fd iomode Nothing{-no stat-}
                             False{-not a socket-}