Skip to content

Commit 1126ba4

Browse files
committed
Use relaxed atomics for thread safety
1 parent 5ba1a20 commit 1126ba4

2 files changed

Lines changed: 15 additions & 8 deletions

File tree

Modules/posixmodule.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11882,9 +11882,12 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
1188211882
/* dup3() is available on Linux 2.6.27+ and glibc 2.9 and macOS 27.0;
1188311883
* it needs runtime detection for the case of running on older kernels.
1188411884
* Values: -1: unknown; 0: doesn't work; 1: works
11885+
* For thread safety, use a process-global with one read & one store,
11886+
* both relaxed. (It's fine if two threads race and do the detection
11887+
* simultaneously; they should get the same result.)
1188511888
*/
11886-
static int dup3_works = -1;
11887-
(void) dup3_works; // unused on some platforms
11889+
static int dup3_works_atomic = -1;
11890+
(void) dup3_works_atomic; // unused on some platforms
1188811891

1188911892
/* dup2() can fail with EINTR if the target FD is already open, because it
1189011893
* then has to be closed. See os_close_impl() for why we don't handle EINTR
@@ -11923,6 +11926,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
1192311926
#else
1192411927

1192511928
#ifdef HAVE_DUP3
11929+
int dup3_works = FT_ATOMIC_LOAD_INT_RELAXED(dup3_works_atomic);
1192611930
if (!inheritable && dup3_works != 0) {
1192711931
if (HAVE_DUP3_RUNTIME) {
1192811932
Py_BEGIN_ALLOW_THREADS
@@ -11931,6 +11935,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
1193111935
if (res < 0) {
1193211936
if (dup3_works == -1) {
1193311937
dup3_works = (errno != ENOSYS);
11938+
FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
1193411939
}
1193511940
if (dup3_works) {
1193611941
posix_error();
@@ -11940,6 +11945,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
1194011945
}
1194111946
else {
1194211947
dup3_works = 0;
11948+
FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
1194311949
}
1194411950
}
1194511951

@@ -12784,11 +12790,10 @@ os_pipe_impl(PyObject *module)
1278412790
int res = -1;
1278512791

1278612792
/* pipe2() is available on some newer linux/glibc & macOS;
12787-
* it needs runtime detection for the case of running on older kernels.
12788-
* Values: -1: unknown; 0: doesn't work; 1: works
12793+
* use the same runtime detection as for dup3 above.
1278912794
*/
12790-
static int pipe2_works = -1;
12791-
(void) pipe2_works; // unused on some platforms
12795+
static int pipe2_works_atomic = -1;
12796+
(void) pipe2_works_atomic; // unused on some platforms
1279212797
#endif
1279312798

1279412799
#ifdef MS_WINDOWS
@@ -12814,6 +12819,7 @@ os_pipe_impl(PyObject *module)
1281412819
#else
1281512820

1281612821
#ifdef HAVE_PIPE2
12822+
int pipe2_works = FT_ATOMIC_LOAD_INT_RELAXED(pipe2_works_atomic);
1281712823
if (pipe2_works != 0) {
1281812824
if (HAVE_PIPE2_RUNTIME) {
1281912825
Py_BEGIN_ALLOW_THREADS
@@ -12827,10 +12833,12 @@ os_pipe_impl(PyObject *module)
1282712833
// pipe2 is present but this call failed
1282812834
pipe2_works = 1;
1282912835
}
12836+
FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
1283012837
}
1283112838
}
1283212839
else {
1283312840
pipe2_works = 0;
12841+
FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
1283412842
}
1283512843
}
1283612844

Tools/c-analyzer/cpython/ignored.tsv

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ Python/bootstrap_hash.c py_getrandom getrandom_works -
1919
Python/bootstrap_hash.c py_getentropy getentropy_works -
2020
Python/fileutils.c - _Py_open_cloexec_works -
2121
Python/fileutils.c set_inheritable ioctl_works -
22-
# (set lazily, *after* first init)
23-
# XXX Is this thread-safe?
22+
# (set lazily, atomically, *after* first init)
2423
Modules/posixmodule.c os_dup2_impl dup3_works -
2524
Modules/posixmodule.c os_pipe_impl pipe2_works -
2625

0 commit comments

Comments
 (0)