Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ghc-fast-logger for openSUSE:Factory
checked in at 2026-11-06 19:48:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-fast-logger (Old)
and /work/SRC/openSUSE:Factory/.ghc-fast-logger.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-fast-logger"
Fri Nov 6 19:48:50 2026 rev:33 rq:1395532 version:3.2.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-fast-logger/ghc-fast-logger.changes
2025-07-02 12:09:11.373934676 +0200
+++
/work/SRC/openSUSE:Factory/.ghc-fast-logger.new.3759290/ghc-fast-logger.changes
2026-11-06 19:55:24.593733808 +0100
@@ -1,0 +2,26 @@
+Tue Oct 27 10:51:32 UTC 2026 - Peter Simons <[email protected]>
+
+- Update fast-logger to version 3.2.9.
+ ## 3.2.9
+
+ * The writer thread of SingleLogger survives write errors such as
+ ENOSPC and EPIPE. The failed messages are dropped.
+
+-------------------------------------------------------------------
+Thu Oct 8 02:30:50 UTC 2026 - Peter Simons <[email protected]>
+
+- Update fast-logger to version 3.2.8.
+ ## 3.2.8
+
+ * Take another road under the Windows native I/O manager
+ [#222](https://github.com/kazu-yamamoto/logger/pull/222)
+
+-------------------------------------------------------------------
+Thu Aug 6 00:55:13 UTC 2026 - Peter Simons <[email protected]>
+
+- Update fast-logger to version 3.2.7.
+ ## 3.2.7
+
+ * Don't eat up an asynchronous exception.
+
+-------------------------------------------------------------------
Old:
----
fast-logger-3.2.6.tar.gz
New:
----
fast-logger-3.2.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-fast-logger.spec ++++++
--- /var/tmp/diff_new_pack.n4OeT5/_old 2026-11-06 19:55:25.616776643 +0100
+++ /var/tmp/diff_new_pack.n4OeT5/_new 2026-11-06 19:55:25.619776769 +0100
@@ -1,7 +1,7 @@
#
# spec file for package ghc-fast-logger
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
%global pkgver %{pkg_name}-%{version}
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 3.2.6
+Version: 3.2.9
Release: 0
Summary: A fast logging system
License: BSD-3-Clause
++++++ fast-logger-3.2.6.tar.gz -> fast-logger-3.2.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/fast-logger-3.2.6/ChangeLog.md
new/fast-logger-3.2.9/ChangeLog.md
--- old/fast-logger-3.2.6/ChangeLog.md 2001-09-09 03:46:40.000000000 +0200
+++ new/fast-logger-3.2.9/ChangeLog.md 2001-09-09 03:46:40.000000000 +0200
@@ -1,3 +1,17 @@
+## 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
+ [#222](https://github.com/kazu-yamamoto/logger/pull/222)
+
+## 3.2.7
+
+* Don't eat up an asynchronous exception.
+
## 3.2.6
* Labeling the thread of SingleLogger.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/fast-logger-3.2.6/System/Log/FastLogger/File.hs
new/fast-logger-3.2.9/System/Log/FastLogger/File.hs
--- old/fast-logger-3.2.6/System/Log/FastLogger/File.hs 2001-09-09
03:46:40.000000000 +0200
+++ new/fast-logger-3.2.9/System/Log/FastLogger/File.hs 2001-09-09
03:46:40.000000000 +0200
@@ -76,6 +76,14 @@
dir = takeDirectory file
-- | Rotating log files.
+--
+-- The log file is renamed while it is still open, which every platform
+-- allows except Windows, and Windows allows it only of a file opened
+-- sharing deletion. The descriptor 'GHC.IO.FD' opens is not, so under the
+-- POSIX subsystem there -- @+RTS --io-manager=posix@, which is still the
+-- default -- this is refused and the file does not rotate. Under the
+-- native one the file is a 'System.IO.Handle', which is shared for
+-- deletion, and it does.
rotate :: FileLogSpec -> IO ()
rotate spec = mapM_ move srcdsts
where
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/fast-logger-3.2.6/System/Log/FastLogger/FileIO.hs
new/fast-logger-3.2.9/System/Log/FastLogger/FileIO.hs
--- old/fast-logger-3.2.6/System/Log/FastLogger/FileIO.hs 2001-09-09
03:46:40.000000000 +0200
+++ new/fast-logger-3.2.9/System/Log/FastLogger/FileIO.hs 2001-09-09
03:46:40.000000000 +0200
@@ -1,4 +1,24 @@
-module System.Log.FastLogger.FileIO where
+{-# LANGUAGE CPP #-}
+
+-- | Where the bytes actually go.
+--
+-- The rest of fast-logger fills its own buffer and hands it here as a raw
+-- pointer, so this is deliberately one layer below 'Handle': the point of
+-- 'writeRawBufferPtr2FD' is that nothing buffers the bytes a second time.
+--
+-- Windows has two I\/O subsystems and chooses between them at run time, from
+-- the @--io-manager=@ RTS flag, so on Windows an 'FD' is one of two things.
+-- See the note on 'openFileFD'.
+module System.Log.FastLogger.FileIO (
+ FD,
+ closeFD,
+ openFileFD,
+ getStderrFD,
+ getStdoutFD,
+ writeRawBufferPtr2FD,
+ invalidFD,
+ isFDValid,
+) where
import Foreign.Ptr (Ptr)
import GHC.IO.Device (close)
@@ -8,6 +28,90 @@
import System.Log.FastLogger.Imports
+#if defined(mingw32_HOST_OS)
+import GHC.IO.SubSystem (isWindowsNativeIO)
+import qualified System.IO as SIO
+#endif
+
+#if defined(mingw32_HOST_OS)
+
+-- | A file descriptor, or on Windows under the native I\/O manager a
+-- 'SIO.Handle' standing in for one.
+data FD
+ = PosixFD !POSIX.FD
+ | -- | Under the native I\/O manager. The 'SIO.Handle' is left with
+ -- whatever buffering it came with and flushed after every write, so
+ -- the bytes are no more buffered than they were before.
+ NativeFD !SIO.Handle
+ | InvalidFD
+
+-- | Opening a log file for appending.
+--
+-- Under the POSIX subsystem this is a file descriptor, as it always was.
+--
+-- Under the native subsystem it cannot be. There a 'POSIX.FD' is a C
+-- runtime descriptor, and the I\/O manager works in terms of Windows
+-- handles registered with a completion port; the two cannot be mixed, and
+-- @base@ says so by replacing every method of @IODevice FD@ and @RawIO FD@
+-- with an @error@ when that subsystem is in force. Opening and the raw
+-- write happen to be plain functions and so still work, which is the trap:
+-- a log file could be written and never closed, and it stayed locked for
+-- the life of the process.
+--
+-- 'SIO.openFile' gives a handle the running subsystem owns, whichever it
+-- is. Appending is its business too, which matters because the native
+-- subsystem writes at an offset given per call and has no @O_APPEND@ of
+-- its own.
+openFileFD :: FilePath -> IO FD
+openFileFD f
+ | isWindowsNativeIO = NativeFD <$> SIO.openFile f SIO.AppendMode
+ | otherwise = PosixFD . fst <$> openFile f AppendMode False
+
+-- | The standard streams are handed to us, not opened by us, and under the
+-- native subsystem the descriptor numbered 1 is not what the process is
+-- actually writing through: bytes put there were accepted and never
+-- appeared.
+getStdoutFD :: IO FD
+getStdoutFD
+ | isWindowsNativeIO = return $ NativeFD SIO.stdout
+ | otherwise = return $ PosixFD stdout
+
+getStderrFD :: IO FD
+getStderrFD
+ | isWindowsNativeIO = return $ NativeFD SIO.stderr
+ | otherwise = return $ PosixFD stderr
+
+-- | Only ever called for a log file, never for a standard stream.
+closeFD :: FD -> IO ()
+closeFD (PosixFD fd) = close fd
+closeFD (NativeFD h) = SIO.hClose h
+closeFD InvalidFD = return ()
+
+writeRawBufferPtr2FD :: IORef FD -> Ptr Word8 -> Int -> IO Int
+writeRawBufferPtr2FD fdref bf len = do
+ fd <- readIORef fdref
+ case fd of
+ PosixFD fd'
+ | POSIX.fdFD fd' /= -1 ->
+ fromIntegral <$> writeRawBufferPtr "write" fd' bf 0
(fromIntegral len)
+ -- 'SIO.hPutBuf' writes all of it or raises; there is no short write
+ -- to report back.
+ NativeFD h -> do
+ SIO.hPutBuf h bf len
+ SIO.hFlush h
+ return len
+ _ -> return (-1)
+
+invalidFD :: FD
+invalidFD = InvalidFD
+
+isFDValid :: FD -> Bool
+isFDValid (PosixFD fd) = POSIX.fdFD fd /= -1
+isFDValid (NativeFD _) = True
+isFDValid InvalidFD = False
+
+#else
+
type FD = POSIX.FD
closeFD :: FD -> IO ()
@@ -36,3 +140,5 @@
isFDValid :: POSIX.FD -> Bool
isFDValid fd = POSIX.fdFD fd /= -1
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/fast-logger-3.2.6/System/Log/FastLogger/SingleLogger.hs
new/fast-logger-3.2.9/System/Log/FastLogger/SingleLogger.hs
--- old/fast-logger-3.2.6/System/Log/FastLogger/SingleLogger.hs 2001-09-09
03:46:40.000000000 +0200
+++ new/fast-logger-3.2.9/System/Log/FastLogger/SingleLogger.hs 2001-09-09
03:46:40.000000000 +0200
@@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/fast-logger-3.2.6/System/Log/FastLogger.hs
new/fast-logger-3.2.9/System/Log/FastLogger.hs
--- old/fast-logger-3.2.6/System/Log/FastLogger.hs 2001-09-09
03:46:40.000000000 +0200
+++ new/fast-logger-3.2.9/System/Log/FastLogger.hs 2001-09-09
03:46:40.000000000 +0200
@@ -47,8 +47,9 @@
) where
import Control.Concurrent (MVar, newMVar, putMVar, tryTakeMVar)
-import Control.Exception (SomeException (..), bracket, handle)
+import Control.Exception (bracket)
import System.EasyFile (getFileSize)
+import qualified System.IO.Error as E
import System.Log.FastLogger.Date
import System.Log.FastLogger.File
@@ -80,30 +81,44 @@
data LogType' a where
LogNone :: LogType' LogStr
-- ^ No logging.
- LogStdout :: BufSize
+ LogStdout
+ :: BufSize
-> LogType' LogStr
-- ^ Logging to stdout.
-- 'BufSize' is a buffer size
-- for each capability.
- LogStderr :: BufSize
+ LogStderr
+ :: BufSize
-> LogType' LogStr
-- ^ Logging to stderr.
-- 'BufSize' is a buffer size
-- for each capability.
- LogFileNoRotate :: FilePath
+ LogFileNoRotate
+ :: FilePath
-> BufSize
-> LogType' LogStr
-- ^ Logging to a file.
-- 'BufSize' is a buffer size
-- for each capability.
- LogFile :: FileLogSpec
+ LogFile
+ :: FileLogSpec
-> BufSize
-> LogType' LogStr
-- ^ Logging to a file.
-- 'BufSize' is a buffer size
-- for each capability.
-- File rotation is done on-demand.
- LogFileTimedRotate :: TimedFileLogSpec
+ --
+ -- On Windows this needs the native I\/O manager
+ -- (@+RTS --io-manager=native@). Rotation renames the
+ -- log file while it is still open, which the
+ -- descriptor the POSIX subsystem opens there is not
+ -- shared for; the rename is refused and the file
+ -- stops rotating. Nothing is lost -- the log keeps
+ -- being written to the one file, past the size asked
+ -- for.
+ LogFileTimedRotate
+ :: TimedFileLogSpec
-> BufSize
-> LogType' LogStr
-- ^ Logging to a file.
@@ -111,7 +126,8 @@
-- for each capability.
-- Rotation happens based on check specified
-- in 'TimedFileLogSpec'.
- LogCallback :: (v -> IO ())
+ LogCallback
+ :: (v -> IO ())
-> IO ()
-> LogType' v
-- ^ Logging with a log and flush action.
@@ -261,11 +277,11 @@
writeIORef ref $ estimate (limit - siz)
file = log_file spec
limit = log_file_size spec
+ -- The log file is locked by GHC.
+ -- We need to get its file size by the way not using locks.
getSize =
- handle (\(SomeException _) -> return Nothing) $
- -- The log file is locked by GHC.
- -- We need to get its file size by the way not using locks.
- Just . fromIntegral <$> getFileSize file
+ (Just . fromIntegral <$> getFileSize file) `E.catchIOError` \_ ->
return Nothing
+
-- 200 is an ad-hoc value for the length of log line.
estimate x = fromInteger (x `div` 200)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/fast-logger-3.2.6/fast-logger.cabal
new/fast-logger-3.2.9/fast-logger.cabal
--- old/fast-logger-3.2.6/fast-logger.cabal 2001-09-09 03:46:40.000000000
+0200
+++ new/fast-logger-3.2.9/fast-logger.cabal 2001-09-09 03:46:40.000000000
+0200
@@ -1,6 +1,6 @@
cabal-version: >=1.10
name: fast-logger
-version: 3.2.6
+version: 3.2.9
license: BSD3
license-file: LICENSE
maintainer: Kazu Yamamoto <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/fast-logger-3.2.6/test/FastLoggerSpec.hs
new/fast-logger-3.2.9/test/FastLoggerSpec.hs
--- old/fast-logger-3.2.6/test/FastLoggerSpec.hs 2001-09-09
03:46:40.000000000 +0200
+++ new/fast-logger-3.2.9/test/FastLoggerSpec.hs 2001-09-09
03:46:40.000000000 +0200
@@ -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