Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Open
Description
Bug report
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 usesetgrent
/getgrent
. It's probably a good time to look for other similar issues.
clang-tidy
clang-tidy
has aconcurrency-mt-unsafe
check that looks for "known-to-be-unsafe functions".
clang-tidy notes
Prerequisites: installclang-tidy-18
andbear
.
./configure -C --with-pydebug --disable-gil# generate compile_commands.jsonbear -- make -j run-clang-tidy-18 -checks='-*,concurrency-mt-unsafe' -p.
Unsafe libc functions
localeconv()
: not thread-safe, seeglibc's manual. Isnl_langinfo
a substitue?setlocale
setpwent
,getpwent
, andendpwent
inpwdmodule.c
. These are similar togrpmodule.c
and can likely be addressed the same way.getservbyname
,getservbyport
,getprotobyname
inModules/socketmodule.c
: usegetservbyname_r
, etc.? Note these thread-safety issues affect the default build because we release the GIL around the relevant calls.dbm_open
,dbm_close
, etc. inModules/_dbmmodule.c
getlogin
: usegetlogin_r
if available?
Unfixable by us?
getenv
,setenv
,unsetenv
,putenv
: environment modification isn't thread-safe andgetenv
is used extensively in other C libraries, so putting a lock around our accesses doesn't do much. (Might finally be fixed in glibc, seehttps://inbox.sourceware.org/libc-alpha/cover.1722193092.git.fweimer@redhat.com/).login_tty
: not sure it matters aslogin_tty
is usually called after afork()
Safe due to our usage
getc_unlocked
, safe because we use it within aflockfile()
call.mbrtowc()
- safe as long as the passed inmbstate_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:
dlerror()
strerror()
: seehttps://man7.org/linux/man-pages/man3/strerror.3.htmlsystem()
: seehttps://man7.org/linux/man-pages/man3/system.3.htmlreaddir(DIR *dirp)
: seehttps://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."wcstombs
: seehttps://man7.org/linux/man-pages/man3/wcstombs.3.htmlnl_langinfo
:https://www.man7.org/linux/man-pages/man3/nl_langinfo.3.html (as long as locale doesn't change)tcsendbreak
,tcflow
: seehttps://www.man7.org/linux/man-pages/man3/termios.3.html#ATTRIBUTESsetlogmask
: safe since glibc 2.33strsignal
: not documented as thread-safe, but uses glibc uses TLS internally since 2.32
Other
exit()
: apparently concurrent calls toexit()
arenot thread-safe, but I don't think it matters for our usages.ptsname()
: we already useptsname_r()
, but the static analyzer gets confused