Skip to content

3.12.4 breakslogging.config.DictConfig with logging.handlers.QueueHandler on read-only file systems #120868

@provinzkraut

Description

@provinzkraut

Bug report

Bug description:

When using logging.config.dictConfig to configure a logging.handlers.QueueHandler on a read only file system, it works fine in 3.12.3, but crashes in 3.12.4.

Reproducing

# bug.py
import logging.config

logging.config.dictConfig(
    {
        "version": 1,
        "handlers": {
            "queue_listener": {
                "class": "logging.handlers.QueueHandler",
                "queue": {"()": "queue.Queue", "maxsize": -1},
            },
        },
    }
)
# Dockerfile
FROM python:3.12.4-slim-bookworm

COPY bug.py ./

CMD ["python", "bug.py"]

Run docker run --rm --read-only -it $(docker build -q .)

Process SyncManager-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/multiprocessing/process.py", line 314, in _bootstrap
    self.run()
  File "/usr/local/lib/python3.12/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.12/multiprocessing/managers.py", line 591, in _run_server
    server = cls._Server(registry, address, authkey, serializer)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/managers.py", line 156, in __init__
    self.listener = Listener(address=address, backlog=128)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 458, in __init__
    address = address or arbitrary_address(family)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 77, in arbitrary_address
    return tempfile.mktemp(prefix='listener-', dir=util.get_temp_dir())
                                                   ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/util.py", line 149, in get_temp_dir
    tempdir = tempfile.mkdtemp(prefix='pymp-')
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 373, in mkdtemp
    prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 126, in _sanitize_params
    dir = gettempdir()
          ^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 315, in gettempdir
    return _os.fsdecode(_gettempdir())
                        ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 308, in _gettempdir
    tempdir = _get_default_tempdir()
              ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/tempfile.py", line 223, in _get_default_tempdir
    raise FileNotFoundError(_errno.ENOENT,
FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/']
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/logging/config.py", line 581, in configure
    handler = self.configure_handler(handlers[name])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/logging/config.py", line 792, in configure_handler
    proxy_queue = MM().Queue()
                  ^^^^
  File "/usr/local/lib/python3.12/multiprocessing/context.py", line 57, in Manager
    m.start()
  File "/usr/local/lib/python3.12/multiprocessing/managers.py", line 566, in start
    self._address = reader.recv()
                    ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 250, in recv
    buf = self._recv_bytes()
          ^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 430, in _recv_bytes
    buf = self._recv(4)
          ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 399, in _recv
    raise EOFError
EOFError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "//bug.py", line 3, in <module>
    logging.config.dictConfig(
  File "/usr/local/lib/python3.12/logging/config.py", line 920, in dictConfig
    dictConfigClass(config).configure()
  File "/usr/local/lib/python3.12/logging/config.py", line 588, in configure
    raise ValueError('Unable to configure handler '
ValueError: Unable to configure handler 'queue_listener'

From my understanding, this is related to #119819 et al. and the change that caused this was introduced in #120030: It introduces creating ephemeral instances of multiprocessing.Manager which, on init, tries to acquire a temporary directory.

proxy_queue = MM().Queue()

CPython versions tested on:

3.12

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy