Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Include/internal/pycore_pyatomic_ft_wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ extern "C" {
_Py_atomic_store_ullong_relaxed(&value, new_value)
#define FT_ATOMIC_LOAD_ULLONG_RELAXED(value) \
_Py_atomic_load_ullong_relaxed(&value)
#define FT_ATOMIC_STORE_INT64_RELAXED(value, new_value) \
_Py_atomic_store_int64_relaxed(&value, new_value)
#define FT_ATOMIC_LOAD_INT64_RELAXED(value) \
_Py_atomic_load_int64_relaxed(&value)

#else
#define FT_ATOMIC_LOAD_PTR(value) value
Expand Down Expand Up @@ -156,6 +160,8 @@ extern "C" {
#define FT_ATOMIC_STORE_LLONG_RELAXED(value, new_value) value = new_value
#define FT_ATOMIC_LOAD_ULLONG_RELAXED(value) value
#define FT_ATOMIC_STORE_ULLONG_RELAXED(value, new_value) value = new_value
#define FT_ATOMIC_LOAD_INT64_RELAXED(value) value
#define FT_ATOMIC_STORE_INT64_RELAXED(value, new_value) value = new_value

#endif

Expand Down
80 changes: 39 additions & 41 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Local naming conventions:
#include "pycore_fileutils.h" // _Py_set_inheritable()
#include "pycore_moduleobject.h" // _PyModule_GetState
#include "pycore_time.h" // _PyTime_AsMilliseconds()
#include "pycore_pyatomic_ft_wrappers.h"

#ifdef _Py_MEMORY_SANITIZER
# include <sanitizer/msan_interface.h>
Expand Down Expand Up @@ -546,23 +547,34 @@ typedef struct _socket_state {
by this module (but not argument type or memory errors, etc.). */
PyObject *socket_herror;
PyObject *socket_gaierror;
} socket_state;

/* Default timeout for new sockets */
static PyTime_t defaulttimeout = _PYTIME_FROMSECONDS(-1);

/* Default timeout for new sockets */
PyTime_t defaulttimeout;
#define SET_DEFAULT_TIMEOUT(timeout) FT_ATOMIC_STORE_INT64_RELAXED(defaulttimeout, timeout)
#define GET_DEFAULT_TIMEOUT() FT_ATOMIC_LOAD_INT64_RELAXED(defaulttimeout)

#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;

#define SET_ACCEPT4_WORKS(value) FT_ATOMIC_STORE_INT_RELAXED(accept4_works, value)
#define GET_ACCEPT4_WORKS() FT_ATOMIC_LOAD_INT_RELAXED(accept4_works)

#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;

#define SET_SOCK_CLOEXEC_WORKS(value) FT_ATOMIC_STORE_INT_RELAXED(sock_cloexec_works, value)
#define GET_SOCK_CLOEXEC_WORKS() FT_ATOMIC_LOAD_INT_RELAXED(sock_cloexec_works)

#endif
} socket_state;

static inline socket_state *
get_module_state(PyObject *mod)
Expand Down Expand Up @@ -1057,7 +1069,7 @@ init_sockobject(socket_state *state, PySocketSockObject *s,
else
#endif
{
s->sock_timeout = _Py_atomic_load_int64_relaxed(&state->defaulttimeout);
s->sock_timeout = GET_DEFAULT_TIMEOUT();
if (s->sock_timeout >= 0) {
if (internal_setblocking(s, 0) == -1) {
return -1;
Expand Down Expand Up @@ -2867,16 +2879,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 (GET_ACCEPT4_WORKS() != 0) {
ctx->result = accept4(s->sock_fd, addr, paddrlen,
SOCK_CLOEXEC);
if (ctx->result == INVALID_SOCKET && state->accept4_works == -1) {
if (ctx->result == INVALID_SOCKET && GET_ACCEPT4_WORKS() == -1) {
/* On Linux older than 2.6.28, accept4() fails with ENOSYS */
state->accept4_works = (errno != ENOSYS);
SET_ACCEPT4_WORKS(errno != ENOSYS);
}
}
if (state->accept4_works == 0)
if (GET_ACCEPT4_WORKS() == 0)
ctx->result = accept(s->sock_fd, addr, paddrlen);
#else
ctx->result = accept(s->sock_fd, addr, paddrlen);
Expand Down Expand Up @@ -2929,8 +2940,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 (!GET_ACCEPT4_WORKS())
#endif
{
if (_Py_set_inheritable(newfd, 0, NULL) < 0) {
Expand Down Expand Up @@ -5391,7 +5401,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
Expand Down Expand Up @@ -5546,15 +5556,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 (GET_SOCK_CLOEXEC_WORKS() != 0) {
fd = socket(family, type | SOCK_CLOEXEC, proto);
if (state->sock_cloexec_works == -1) {
if (GET_SOCK_CLOEXEC_WORKS() == -1) {
if (fd >= 0) {
state->sock_cloexec_works = 1;
SET_SOCK_CLOEXEC_WORKS(1);
}

else if (errno == EINVAL) {
/* Linux older than 2.6.27 does not support SOCK_CLOEXEC */
state->sock_cloexec_works = 0;
SET_SOCK_CLOEXEC_WORKS(0);
fd = socket(family, type, proto);
}
}
Expand Down Expand Up @@ -6295,7 +6306,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
Expand All @@ -6313,15 +6324,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 (GET_SOCK_CLOEXEC_WORKS() != 0) {
ret = socketpair(family, type | SOCK_CLOEXEC, proto, sv);
if (state->sock_cloexec_works == -1) {
if (GET_SOCK_CLOEXEC_WORKS() == -1) {
if (ret >= 0) {
state->sock_cloexec_works = 1;
SET_SOCK_CLOEXEC_WORKS(1);
}
else if (errno == EINVAL) {
/* Linux older than 2.6.27 does not support SOCK_CLOEXEC */
state->sock_cloexec_works = 0;
SET_SOCK_CLOEXEC_WORKS(0);
ret = socketpair(family, type, proto, sv);
}
}
Expand Down Expand Up @@ -6957,8 +6968,7 @@ Get host and port for a sockaddr.");
static PyObject *
socket_getdefaulttimeout(PyObject *self, PyObject *Py_UNUSED(ignored))
{
socket_state *state = get_module_state(self);
PyTime_t timeout = _Py_atomic_load_int64_relaxed(&state->defaulttimeout);
PyTime_t timeout = GET_DEFAULT_TIMEOUT();
if (timeout < 0) {
Py_RETURN_NONE;
}
Expand All @@ -6983,8 +6993,7 @@ socket_setdefaulttimeout(PyObject *self, PyObject *arg)
if (socket_parse_timeout(&timeout, arg) < 0)
return NULL;

socket_state *state = get_module_state(self);
_Py_atomic_store_int64_relaxed(&state->defaulttimeout, timeout);
SET_DEFAULT_TIMEOUT(timeout);

Py_RETURN_NONE;
}
Expand Down Expand Up @@ -7429,17 +7438,6 @@ 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

#define ADD_EXC(MOD, NAME, VAR, BASE) do { \
VAR = PyErr_NewException("socket." NAME, BASE, NULL); \
Expand Down
6 changes: 3 additions & 3 deletions Python/fileutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,6 @@ Modules/readline.c - completed_input_string -
Modules/rotatingtree.c - random_stream -
Modules/rotatingtree.c - random_value -
Modules/rotatingtree.c - random_mutex -
Modules/socketmodule.c - defaulttimeout -
Modules/socketmodule.c - accept4_works -
Modules/socketmodule.c - sock_cloexec_works -
Loading