There are a a few non thread-safe libc functions used in Python that can be an issue for free threading, isolated subinterpreters, or sometimes even with the GIL.
In #126316, @vstinner fixed the use setgrent / getgrent. It's probably a good time to look for other similar issues.
clang-tidy
clang-tidy has a concurrency-mt-unsafe check that looks for "known-to-be-unsafe functions".
setpwent, getpwent, and endpwent in pwdmodule.c. These are similar to grpmodule.c and can likely be addressed the same way.
getservbyname, getservbyport, getprotobyname in Modules/socketmodule.c: use getservbyname_r, etc.? Note these thread-safety issues affect the default build because we release the GIL around the relevant calls.
login_tty: not sure it matters as login_tty is usually called after a fork()
Safe due to our usage
getc_unlocked, safe because we use it within a flockfile() call.
mbrtowc() - safe as long as the passed in mbstate_t * is non-NULL, which is the case in CPython.
Safe in glibc
These functions are flagged by clang-tidy because they are not guaranteed to be safe by POSIX, but they are safe in glibc. It'd be nice to verify that they are safe in other libc implementations. I don't think it's worth changing them:
readdir(DIR *dirp): see https://man7.org/linux/man-pages/man3/readdir.3.html: "...in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe."
I can't reproduce a problem with getlogin at the moment: perhaps using docker or such-like and messing with /var/run/utmp would work.
The issues with setlocale and localeconv look rather more involved. Perhaps replace use of setlocale with uselocale where it is used to temporarily change locale? Various other places need to set it globally for the process, including os.setlocale(), so presumably cannot be changed. Hopefully the documentation stating it is not thread-safe is sufficient there.
Activity
duaneg commented on Apr 16, 2025
This reliably reproduces the race in the socket functions, with or without the GIL:
repro-127081-sockets.pypythongh-127081: use re-entrant variants of get{proto,serv}by{name,port}
duaneg commented on Apr 17, 2025
Reproductions for pwd and dbm issues (only affects free-threaded builds).
repro-127081-pwd.pyI can't reproduce a problem with getlogin at the moment: perhaps using docker or such-like and messing with /var/run/utmp would work.
The issues with setlocale and localeconv look rather more involved. Perhaps replace use of setlocale with uselocale where it is used to temporarily change locale? Various other places need to set it globally for the process, including os.setlocale(), so presumably cannot be changed. Hopefully the documentation stating it is not thread-safe is sufficient there.
pythongh-127081: lock non-re-entrant *pwent calls
pythongh-127081: add critical sections to dbm objects
pythongh-127081: use getlogin_r if available
duaneg commented on Apr 20, 2025
See also #74667, which is a dup of this (or vice versa) specifically regarding the socket functions.
pythongh-127081: add critical sections to dbm objects
pythongh-127081: lock non-re-entrant *pwent calls
pythongh-127081: use re-entrant variants of get{proto,serv}by{name,port}
pythongh-127081: use getlogin_r if available
4 remaining items
gh-127081: use `getlogin_r` if available (gh-132751)
pythongh-127081: use `getlogin_r` if available (pythongh-132751)
[3.13] pythongh-127081: use `getlogin_r` if available (pythongh-132751)
[3.13] gh-127081: use `getlogin_r` if available (gh-132751) (#135098)
[3.14] gh-127081: use `getlogin_r` if available (gh-132751) (gh-135097)
pythongh-127081: add critical sections to `dbm` objects (pythongh-132749
pythongh-127081: lock non-re-entrant `*pwent` calls in free-threading (…
pythongh-127081: use `getlogin_r` if available (pythongh-132751)
pythongh-127081: add critical sections to `dbm` objects (pythongh-132749
pythongh-127081: lock non-re-entrant `*pwent` calls in free-threading (…
pythongh-127081: use `getlogin_r` if available (pythongh-132751)
pythongh-127081: use `getlogin_r` if available (pythongh-132751)
pythongh-127081: add critical sections to `dbm` objects (pythongh-132749
[3.14] gh-127081: add critical sections to `dbm` objects (gh-132749) (#…
pythongh-127081: lock non-re-entrant `*pwent` calls in free-threading (…