summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKumar Aditya <kumaraditya@python.org>2024-12-31 13:40:06 (GMT)
committerGitHub <noreply@github.com>2024-12-31 13:40:06 (GMT)
commite389d6c650ddacb55b08b657f1e4e9b1330f3455 (patch)
tree1a7593dbd97e310e8a5b31dafe24e5274c8a1f3f
parentb2ac70a62ad1be8e037ce45ccf5f1b753ea5e64b (diff)
downloadcpython-e389d6c650ddacb55b08b657f1e4e9b1330f3455.zip
cpython-e389d6c650ddacb55b08b657f1e4e9b1330f3455.tar.gz
cpython-e389d6c650ddacb55b08b657f1e4e9b1330f3455.tar.bz2
gh-128277: make globals variables thread safe in socket module (#128286)
-rw-r--r--Modules/socketmodule.c56
-rw-r--r--Python/fileutils.c6
-rw-r--r--Tools/c-analyzer/cpython/globals-to-fix.tsv2
3 files changed, 28 insertions, 36 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 1f0cbf6..efc8be3 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -550,20 +550,20 @@ typedef struct _socket_state {
/* Default timeout for new sockets */
PyTime_t defaulttimeout;
+} socket_state;
#if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4)
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
- /* accept4() is available on Linux 2.6.28+ and glibc 2.10 */
- int accept4_works;
+/* accept4() is available on Linux 2.6.28+ and glibc 2.10 */
+static int accept4_works = -1;
#endif
#endif
#ifdef SOCK_CLOEXEC
- /* socket() and socketpair() fail with EINVAL on Linux kernel older
- * than 2.6.27 if SOCK_CLOEXEC flag is set in the socket type. */
- int sock_cloexec_works;
+/* socket() and socketpair() fail with EINVAL on Linux kernel older
+ * than 2.6.27 if SOCK_CLOEXEC flag is set in the socket type. */
+static int sock_cloexec_works = -1;
#endif
-} socket_state;
static inline void
set_sock_fd(PySocketSockObject *s, SOCKET_T fd)
@@ -2904,16 +2904,15 @@ sock_accept_impl(PySocketSockObject *s, void *data)
#endif
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
- socket_state *state = s->state;
- if (state->accept4_works != 0) {
+ if (_Py_atomic_load_int_relaxed(&accept4_works) != 0) {
ctx->result = accept4(get_sock_fd(s), addr, paddrlen,
SOCK_CLOEXEC);
- if (ctx->result == INVALID_SOCKET && state->accept4_works == -1) {
+ if (ctx->result == INVALID_SOCKET && _Py_atomic_load_int_relaxed(&accept4_works) == -1) {
/* On Linux older than 2.6.28, accept4() fails with ENOSYS */
- state->accept4_works = (errno != ENOSYS);
+ _Py_atomic_store_int_relaxed(&accept4_works, errno != ENOSYS);
}
}
- if (state->accept4_works == 0)
+ if (_Py_atomic_load_int_relaxed(&accept4_works) == 0)
ctx->result = accept(get_sock_fd(s), addr, paddrlen);
#else
ctx->result = accept(get_sock_fd(s), addr, paddrlen);
@@ -2966,8 +2965,7 @@ sock_accept(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
#else
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
- socket_state *state = s->state;
- if (!state->accept4_works)
+ if (!_Py_atomic_load_int_relaxed(&accept4_works))
#endif
{
if (_Py_set_inheritable(newfd, 0, NULL) < 0) {
@@ -5428,7 +5426,7 @@ sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto,
#ifndef MS_WINDOWS
#ifdef SOCK_CLOEXEC
- int *atomic_flag_works = &state->sock_cloexec_works;
+ int *atomic_flag_works = &sock_cloexec_works;
#else
int *atomic_flag_works = NULL;
#endif
@@ -5583,15 +5581,16 @@ sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto,
/* UNIX */
Py_BEGIN_ALLOW_THREADS
#ifdef SOCK_CLOEXEC
- if (state->sock_cloexec_works != 0) {
+ if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) != 0) {
fd = socket(family, type | SOCK_CLOEXEC, proto);
- if (state->sock_cloexec_works == -1) {
+ if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) == -1) {
if (fd >= 0) {
- state->sock_cloexec_works = 1;
+ _Py_atomic_store_int_relaxed(&sock_cloexec_works, 1);
}
+
else if (errno == EINVAL) {
/* Linux older than 2.6.27 does not support SOCK_CLOEXEC */
- state->sock_cloexec_works = 0;
+ _Py_atomic_store_int_relaxed(&sock_cloexec_works, 0);
fd = socket(family, type, proto);
}
}
@@ -6332,7 +6331,7 @@ socket_socketpair(PyObject *self, PyObject *args)
PyObject *res = NULL;
socket_state *state = get_module_state(self);
#ifdef SOCK_CLOEXEC
- int *atomic_flag_works = &state->sock_cloexec_works;
+ int *atomic_flag_works = &sock_cloexec_works;
#else
int *atomic_flag_works = NULL;
#endif
@@ -6350,15 +6349,15 @@ socket_socketpair(PyObject *self, PyObject *args)
/* Create a pair of socket fds */
Py_BEGIN_ALLOW_THREADS
#ifdef SOCK_CLOEXEC
- if (state->sock_cloexec_works != 0) {
+ if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) != 0) {
ret = socketpair(family, type | SOCK_CLOEXEC, proto, sv);
- if (state->sock_cloexec_works == -1) {
+ if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) == -1) {
if (ret >= 0) {
- state->sock_cloexec_works = 1;
+ _Py_atomic_store_int_relaxed(&sock_cloexec_works, 1);
}
else if (errno == EINVAL) {
/* Linux older than 2.6.27 does not support SOCK_CLOEXEC */
- state->sock_cloexec_works = 0;
+ _Py_atomic_store_int_relaxed(&sock_cloexec_works, 0);
ret = socketpair(family, type, proto, sv);
}
}
@@ -7466,17 +7465,8 @@ socket_exec(PyObject *m)
}
socket_state *state = get_module_state(m);
- state->defaulttimeout = _PYTIME_FROMSECONDS(-1);
-
-#if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4)
-#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
- state->accept4_works = -1;
-#endif
-#endif
-#ifdef SOCK_CLOEXEC
- state->sock_cloexec_works = -1;
-#endif
+ _Py_atomic_store_int64_relaxed(&state->defaulttimeout, _PYTIME_FROMSECONDS(-1));
#define ADD_EXC(MOD, NAME, VAR, BASE) do { \
VAR = PyErr_NewException("socket." NAME, BASE, NULL); \
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 9529b14..8127665 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -1468,14 +1468,14 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
assert(!(atomic_flag_works != NULL && inheritable));
if (atomic_flag_works != NULL && !inheritable) {
- if (*atomic_flag_works == -1) {
+ if (_Py_atomic_load_int_relaxed(atomic_flag_works) == -1) {
int isInheritable = get_inheritable(fd, raise);
if (isInheritable == -1)
return -1;
- *atomic_flag_works = !isInheritable;
+ _Py_atomic_store_int_relaxed(atomic_flag_works, !isInheritable);
}
- if (*atomic_flag_works)
+ if (_Py_atomic_load_int_relaxed(atomic_flag_works))
return 0;
}
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index a1ec192..a747798 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -444,3 +444,5 @@ Modules/readline.c - completed_input_string -
Modules/rotatingtree.c - random_stream -
Modules/rotatingtree.c - random_value -
Modules/rotatingtree.c - random_mutex -
+Modules/socketmodule.c - accept4_works -
+Modules/socketmodule.c - sock_cloexec_works -