Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sysconfig.get_config_var is not thread-safe #92452

Closed
gareth-rees opened this issue May 8, 2022 · 0 comments · Fixed by #92453
Closed

sysconfig.get_config_var is not thread-safe #92452

gareth-rees opened this issue May 8, 2022 · 0 comments · Fixed by #92453
Labels
type-bug An unexpected behavior, bug, or error

Comments

@gareth-rees
Copy link
Contributor

Reproducer

This program starts many threads racing to call sysconfig.get_config_var:

import sysconfig
from multiprocessing.pool import ThreadPool

def thread(i):
    assert sysconfig.get_config_var("srcdir") is not None

with ThreadPool() as pool:
    pool.map(thread, range(100))

When run with Python 3.11.0, this asserts as follows:

Traceback (most recent call last):
  File "/home/grees/core/junk.py", line 8, in <module>
    pool.map(thread, range(100))
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/grees/github.com/cpython/Lib/multiprocessing/pool.py", line 364, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/grees/github.com/cpython/Lib/multiprocessing/pool.py", line 771, in get
    raise self._value
    ^^^^^^^^^^^^^^^^^
  File "/home/grees/github.com/cpython/Lib/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "/home/grees/github.com/cpython/Lib/multiprocessing/pool.py", line 48, in mapstar
    return list(map(*args))
           ^^^^^^^^^^^^^^^^
  File "/home/grees/core/junk.py", line 5, in thread
    assert sysconfig.get_config_var("srcdir") is not None
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError

Analysis

In the sysconfig module, get_config_var calls get_config_vars which initializes the global variable _CONFIG_VARS in a thread-unsafe manner.

Use case

The reproducer above is simplified from a multi-threaded build system. Each build thread needs to get some information from sysconfig, so that the threads are racing to be the first to call get_config_vars.

Workaround

Adding an initial call to get_config_vars before starting any thread ensures that _CONFIG_VARS is reliably initialized.

@gareth-rees gareth-rees added the type-bug An unexpected behavior, bug, or error label May 8, 2022
FFY00 added a commit that referenced this issue Oct 28, 2022
Co-authored-by: Filipe Laíns <lains@riseup.net>
gvanrossum pushed a commit to gvanrossum/cpython that referenced this issue Oct 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
Development

Successfully merging a pull request may close this issue.

1 participant