diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,8 @@
+## 3.2.9
+
+* The writer thread of SingleLogger survives write errors such as
+  ENOSPC and EPIPE. The failed messages are dropped.
+
 ## 3.2.8
 
 * Take another road under the Windows native I/O manager
diff --git a/System/Log/FastLogger/SingleLogger.hs b/System/Log/FastLogger/SingleLogger.hs
--- a/System/Log/FastLogger/SingleLogger.hs
+++ b/System/Log/FastLogger/SingleLogger.hs
@@ -7,6 +7,7 @@
 
 import Control.Concurrent (MVar, forkIO, newEmptyMVar, putMVar, takeMVar)
 import Control.Concurrent.STM
+import qualified Control.Exception as E
 import GHC.Conc.Sync (labelThread)
 
 import System.Log.FastLogger.FileIO
@@ -58,9 +59,21 @@
     go (F mvar cont : msgs) = do
         putMVar mvar ()
         if cont then go msgs else return False
-    go (L msg@(LogStr len _) : msgs)
-        | len <= bufsize = writeLogStr buf fdref msg >> go msgs
-        | otherwise = writeBigLogStr fdref msg >> go msgs
+    go (L msg@(LogStr len _) : msgs) = do
+        dropOnSyncException $
+            if len <= bufsize
+                then writeLogStr buf fdref msg
+                else writeBigLogStr fdref msg
+        go msgs
+
+-- If writing fails (e.g. ENOSPC or EPIPE), the message is dropped
+-- so that the writer thread keeps running and flushes do not block.
+dropOnSyncException :: IO () -> IO ()
+dropOnSyncException act = act `E.catch` handler
+  where
+    handler e = case E.fromException e of
+        Just (E.SomeAsyncException _) -> E.throwIO e
+        Nothing -> return ()
 
 ----------------------------------------------------------------
 
diff --git a/fast-logger.cabal b/fast-logger.cabal
--- a/fast-logger.cabal
+++ b/fast-logger.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               fast-logger
-version:            3.2.8
+version:            3.2.9
 license:            BSD3
 license-file:       LICENSE
 maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>
diff --git a/test/FastLoggerSpec.hs b/test/FastLoggerSpec.hs
--- a/test/FastLoggerSpec.hs
+++ b/test/FastLoggerSpec.hs
@@ -17,6 +17,11 @@
 #endif
 import Data.String (IsString (fromString))
 import System.Directory (doesFileExist, removeFile)
+#if !defined(mingw32_HOST_OS)
+import qualified GHC.IO.FD as FD
+import GHC.IO.IOMode (IOMode (ReadMode))
+#endif
+import System.Timeout (timeout)
 import Text.Printf (printf)
 
 import Test.Hspec
@@ -52,6 +57,7 @@
 
     describe "fastlogger 1" $ do
         it "maintains the ordering of log messages" logOrdering
+        it "survives write errors" survivesWriteErrors
 
 tempFile :: FilePath
 tempFile = "test/temp.txt"
@@ -113,3 +119,17 @@
   where
     mktag :: Int -> String
     mktag t = "thread id: " <> show t <> " "
+
+survivesWriteErrors :: IO ()
+#if defined(mingw32_HOST_OS)
+survivesWriteErrors = pendingWith "POSIX only"
+#else
+survivesWriteErrors = do
+    -- Writing to a read-only FD fails with EBADF.
+    (fd, _) <- FD.openFile "LICENSE" ReadMode False
+    lgrset <- newFDLoggerSet 512 (Just 1) Nothing fd
+    let msg = toLogStr (BS.replicate 100 'x') <> "\n"
+    mapM_ (\_ -> pushLogStr lgrset msg) [1 .. 100 :: Int]
+    timeout 3000000 (flushLogStr lgrset) `shouldReturn` Just ()
+    timeout 3000000 (rmLoggerSet lgrset) `shouldReturn` Just ()
+#endif
