Repository navigation
0.9.30
What's Changed
-
0.9.30
-
Mark Python 3.15 as supported.
-
Fix permission race window between file create and chmod, when the
chmodand/orownerkwargs are configured.
Issue #87The handler created files using the configured
umaskand applied_do_chown_and_chmod()afterward. In the
window between create and chmod, the file was visible in the filesystem with umask-derived (potentially
too-restrictive) permissions. A different-user process that opened the file during this window got
PermissionError, breaking the cross-user log sharing scenario thechmod/ownerkwargs exist to support.The lock file, the main log file, and rotated
.gzfiles (from both handlers) are now pre-created atomically
with the correct permissions: a hidden temp file gets the owner and mode, thenos.link()(POSIX) or
os.rename()(Windows) puts it in place. Other processes never see the public filename with intermediate
perms. On filesystems without hard links (FAT/exFAT, many SMB/CIFS and FUSE mounts), the handler falls back to
the previous create-then-chmod behavior. Handlers that don't configurechmod/ownerare unaffected and pay
no extra syscalls. -
Fix lost records when a process opens a lock file or log file that another user owns, with
chmodorowner
configured. Only the owner of a file (or root) can chmod it, so every write from that process failed with
PermissionError, even though the file was writable. The handler now skips chmod/chown when the file already
has the configured mode and owner, and treats a failure as non-fatal (reported only indebugmode). Related
to Issue #87. -
ConcurrentTimedRotatingFileHandlerno longer creates the log file in its constructor. The standard library
created it there with the process umask, so the handler'sumask,chmod, andownersettings did not apply
until the first write. Until then, a process running as another user could fail to create its handler, with
PermissionError. The file is now created on first write, as inConcurrentRotatingFileHandler, and the
delayargument is ignored. -
ConcurrentTimedRotatingFileHandlernow applieschmodandownerto rotated.gzfiles. Before, they kept
umask-derived permissions. -
Fix
do_gzip()silently ignoring the configuredumaskparameter on rotated.gzfiles. Thegzip.open()
call previously ran outside the_alter_umask()context, so rotated archives picked up the process default
umask instead of the handler's. Discovered while investigating Issue #87. -
Fix a deadlock introduced in 0.9.29. If one thread was writing a log record when another thread called
fork(), the child process hung on its first log call. The child now resets the handler's thread lock. In the
same situation, a child that closed the handler before it logged (for example, throughlogging.shutdown()
at exit) released the parent's file lock while the parent was still writing. The child now also clears the
inherited lock state. Both fixes apply to Python 3.9 and later; on 3.7 and 3.8, logging holds handler locks
acrossfork(), so these problems do not occur. -
Fix loss of a rotated log file after a failed gzip (for example, disk full). The failure leaves the rotated
file uncompressed. On the next rotation,ConcurrentRotatingFileHandlerdeleted that file (even when
backupCountallowed more), andConcurrentTimedRotatingFileHandlercould overwrite it with a later file from
the same period. Both handlers now keep it. -
Remove a duplicate stale-file check from each write. On a local disk this cuts the time per write by about
13% whenmaxBytesis set, for both handlers.
-
Full Changelog: 0.9.29...0.9.30