]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-128277: use relaxed atomics for `sock_fd` (#128304)
authorKumar Aditya <kumaraditya@python.org>
Tue, 31 Dec 2024 06:20:35 +0000 (11:50 +0530)
committerGitHub <noreply@github.com>
Tue, 31 Dec 2024 06:20:35 +0000 (11:50 +0530)
Modules/socketmodule.c

index 1e95be9b1bc9f4ff4b38db9490f4a501a93e0a12..1f0cbf6abb184c8e90d507f863ba148651812bcd 100644 (file)
@@ -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>
@@ -564,6 +565,42 @@ typedef struct _socket_state {
 #endif
 } socket_state;
 
+static inline void
+set_sock_fd(PySocketSockObject *s, SOCKET_T fd)
+{
+#ifdef Py_GIL_DISABLED
+#if SIZEOF_SOCKET_T == SIZEOF_INT
+    _Py_atomic_store_int_relaxed((int *)&s->sock_fd, (int)fd);
+#elif SIZEOF_SOCKET_T == SIZEOF_LONG
+    _Py_atomic_store_long_relaxed((long *)&s->sock_fd, (long)fd);
+#elif SIZEOF_SOCKET_T == SIZEOF_LONG_LONG
+    _Py_atomic_store_llong_relaxed((long long *)&s->sock_fd, (long long)fd);
+#else
+    #error "Unsupported SIZEOF_SOCKET_T"
+#endif
+#else
+    s->sock_fd = fd;
+#endif
+}
+
+static inline SOCKET_T
+get_sock_fd(PySocketSockObject *s)
+{
+#ifdef Py_GIL_DISABLED
+#if SIZEOF_SOCKET_T == SIZEOF_INT
+    return (SOCKET_T)_Py_atomic_load_int_relaxed((int *)&s->sock_fd);
+#elif SIZEOF_SOCKET_T == SIZEOF_LONG
+    return (SOCKET_T)_Py_atomic_load_long_relaxed((long *)&s->sock_fd);
+#elif SIZEOF_SOCKET_T == SIZEOF_LONG_LONG
+    return (SOCKET_T)_Py_atomic_load_llong_relaxed((long long *)&s->sock_fd);
+#else
+    #error "Unsupported SIZEOF_SOCKET_T"
+#endif
+#else
+    return s->sock_fd;
+#endif
+}
+
 static inline socket_state *
 get_module_state(PyObject *mod)
 {
@@ -736,10 +773,10 @@ internal_setblocking(PySocketSockObject *s, int block)
 #ifndef MS_WINDOWS
 #if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO))
     block = !block;
-    if (ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block) == -1)
+    if (ioctl(get_sock_fd(s), FIONBIO, (unsigned int *)&block) == -1)
         goto done;
 #else
-    delay_flag = fcntl(s->sock_fd, F_GETFL, 0);
+    delay_flag = fcntl(get_sock_fd(s), F_GETFL, 0);
     if (delay_flag == -1)
         goto done;
     if (block)
@@ -747,12 +784,12 @@ internal_setblocking(PySocketSockObject *s, int block)
     else
         new_delay_flag = delay_flag | O_NONBLOCK;
     if (new_delay_flag != delay_flag)
-        if (fcntl(s->sock_fd, F_SETFL, new_delay_flag) == -1)
+        if (fcntl(get_sock_fd(s), F_SETFL, new_delay_flag) == -1)
             goto done;
 #endif
 #else /* MS_WINDOWS */
     arg = !block;
-    if (ioctlsocket(s->sock_fd, FIONBIO, &arg) != 0)
+    if (ioctlsocket(get_sock_fd(s), FIONBIO, &arg) != 0)
         goto done;
 #endif /* MS_WINDOWS */
 
@@ -792,13 +829,13 @@ internal_select(PySocketSockObject *s, int writing, PyTime_t interval,
     assert(!(connect && !writing));
 
     /* Guard against closed socket */
-    if (s->sock_fd == INVALID_SOCKET)
+    if (get_sock_fd(s) == INVALID_SOCKET)
         return 0;
 
     /* Prefer poll, if available, since you can poll() any fd
      * which can't be done with select(). */
 #ifdef HAVE_POLL
-    pollfd.fd = s->sock_fd;
+    pollfd.fd = get_sock_fd(s);
     pollfd.events = writing ? POLLOUT : POLLIN;
     if (connect) {
         /* On Windows, the socket becomes writable on connection success,
@@ -838,23 +875,23 @@ internal_select(PySocketSockObject *s, int writing, PyTime_t interval,
         tvp = NULL;
 
     FD_ZERO(&fds);
-    FD_SET(s->sock_fd, &fds);
+    FD_SET(get_sock_fd(s), &fds);
     FD_ZERO(&efds);
     if (connect) {
         /* On Windows, the socket becomes writable on connection success,
            but a connection failure is notified as an error. On POSIX, the
            socket becomes writable on connection success or on connection
            failure. */
-        FD_SET(s->sock_fd, &efds);
+        FD_SET(get_sock_fd(s), &efds);
     }
 
     /* See if the socket is ready */
     Py_BEGIN_ALLOW_THREADS;
     if (writing)
-        n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
+        n = select(Py_SAFE_DOWNCAST(get_sock_fd(s)+1, SOCKET_T, int),
                    NULL, &fds, &efds, tvp);
     else
-        n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
+        n = select(Py_SAFE_DOWNCAST(get_sock_fd(s)+1, SOCKET_T, int),
                    &fds, NULL, &efds, tvp);
     Py_END_ALLOW_THREADS;
 #endif
@@ -1030,7 +1067,7 @@ static int
 init_sockobject(socket_state *state, PySocketSockObject *s,
                 SOCKET_T fd, int family, int type, int proto)
 {
-    s->sock_fd = fd;
+    set_sock_fd(s, fd);
     s->sock_family = family;
 
     s->sock_type = type;
@@ -2127,7 +2164,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
         }
         strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
         ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
-        if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
+        if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) {
             s->errorhandler();
             PyBuffer_Release(&haddr);
             return 0;
@@ -2252,7 +2289,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
             } else if ((size_t)len < sizeof(ifr.ifr_name)) {
                 strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name));
                 ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
-                if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
+                if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) {
                     s->errorhandler();
                     Py_DECREF(interfaceName);
                     return 0;
@@ -2296,7 +2333,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
             } else if ((size_t)len < sizeof(ifr.ifr_name)) {
                 strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name));
                 ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
-                if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
+                if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) {
                     s->errorhandler();
                     Py_DECREF(interfaceName);
                     return 0;
@@ -2344,7 +2381,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
             } else if ((size_t)len < sizeof(ifr.ifr_name)) {
                 strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name));
                 ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
-                if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
+                if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) {
                     s->errorhandler();
                     Py_DECREF(interfaceName);
                     return 0;
@@ -2403,7 +2440,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
                         sizeof(info.ctl_name));
                 Py_DECREF(ctl_name);
 
-                if (ioctl(s->sock_fd, CTLIOCGINFO, &info)) {
+                if (ioctl(get_sock_fd(s), CTLIOCGINFO, &info)) {
                     PyErr_SetString(PyExc_OSError,
                           "cannot find kernel control with provided name");
                     return 0;
@@ -2869,7 +2906,7 @@ sock_accept_impl(PySocketSockObject *s, void *data)
 #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
     socket_state *state = s->state;
     if (state->accept4_works != 0) {
-        ctx->result = accept4(s->sock_fd, addr, paddrlen,
+        ctx->result = accept4(get_sock_fd(s), addr, paddrlen,
                               SOCK_CLOEXEC);
         if (ctx->result == INVALID_SOCKET && state->accept4_works == -1) {
             /* On Linux older than 2.6.28, accept4() fails with ENOSYS */
@@ -2877,9 +2914,9 @@ sock_accept_impl(PySocketSockObject *s, void *data)
         }
     }
     if (state->accept4_works == 0)
-        ctx->result = accept(s->sock_fd, addr, paddrlen);
+        ctx->result = accept(get_sock_fd(s), addr, paddrlen);
 #else
-    ctx->result = accept(s->sock_fd, addr, paddrlen);
+    ctx->result = accept(get_sock_fd(s), addr, paddrlen);
 #endif
 
 #ifdef MS_WINDOWS
@@ -2946,7 +2983,7 @@ sock_accept(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
         goto finally;
     }
 
-    addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf),
+    addr = makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf),
                         addrlen, s->sock_proto);
     if (addr == NULL)
         goto finally;
@@ -3158,7 +3195,7 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
         if (PyArg_ParseTuple(args, "iiK:setsockopt",
                          &level, &optname, &vflag)) {
             // level should always be set to AF_VSOCK
-            res = setsockopt(s->sock_fd, level, optname,
+            res = setsockopt(get_sock_fd(s), level, optname,
                          (void*)&vflag, sizeof vflag);
             goto done;
         }
@@ -3172,7 +3209,7 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
 #ifdef MS_WINDOWS
         if (optname == SIO_TCP_SET_ACK_FREQUENCY) {
             int dummy;
-            res = WSAIoctl(s->sock_fd, SIO_TCP_SET_ACK_FREQUENCY, &flag,
+            res = WSAIoctl(get_sock_fd(s), SIO_TCP_SET_ACK_FREQUENCY, &flag,
                            sizeof(flag), NULL, 0, &dummy, NULL, NULL);
             if (res >= 0) {
                 s->quickack = flag;
@@ -3180,7 +3217,7 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
             goto done;
         }
 #endif
-        res = setsockopt(s->sock_fd, level, optname,
+        res = setsockopt(get_sock_fd(s), level, optname,
                          (char*)&flag, sizeof flag);
         goto done;
     }
@@ -3190,7 +3227,7 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
     if (PyArg_ParseTuple(args, "iiO!I:setsockopt",
                          &level, &optname, Py_TYPE(Py_None), &none, &optlen)) {
         assert(sizeof(socklen_t) >= sizeof(unsigned int));
-        res = setsockopt(s->sock_fd, level, optname,
+        res = setsockopt(get_sock_fd(s), level, optname,
                          NULL, (socklen_t)optlen);
         goto done;
     }
@@ -3209,10 +3246,10 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
                         INT_MAX);
         return NULL;
     }
-    res = setsockopt(s->sock_fd, level, optname,
+    res = setsockopt(get_sock_fd(s), level, optname,
                         optval.buf, (int)optval.len);
 #else
-    res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len);
+    res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len);
 #endif
     PyBuffer_Release(&optval);
 
@@ -3259,7 +3296,7 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
         if (s->sock_family == AF_VSOCK) {
             uint64_t vflag = 0; // Must be set width of 64 bits
             flagsize = sizeof vflag;
-            res = getsockopt(s->sock_fd, level, optname,
+            res = getsockopt(get_sock_fd(s), level, optname,
                          (void *)&vflag, &flagsize);
             if (res < 0)
                 return s->errorhandler();
@@ -3272,7 +3309,7 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
         }
 #endif
         flagsize = sizeof flag;
-        res = getsockopt(s->sock_fd, level, optname,
+        res = getsockopt(get_sock_fd(s), level, optname,
                          (void *)&flag, &flagsize);
         if (res < 0)
             return s->errorhandler();
@@ -3293,7 +3330,7 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
     buf = PyBytes_FromStringAndSize((char *)NULL, buflen);
     if (buf == NULL)
         return NULL;
-    res = getsockopt(s->sock_fd, level, optname,
+    res = getsockopt(get_sock_fd(s), level, optname,
                      (void *)PyBytes_AS_STRING(buf), &buflen);
     if (res < 0) {
         Py_DECREF(buf);
@@ -3330,7 +3367,7 @@ sock_bind(PySocketSockObject *s, PyObject *addro)
     }
 
     Py_BEGIN_ALLOW_THREADS
-    res = bind(s->sock_fd, SAS2SA(&addrbuf), addrlen);
+    res = bind(get_sock_fd(s), SAS2SA(&addrbuf), addrlen);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return s->errorhandler();
@@ -3367,9 +3404,9 @@ _socket_socket_close_impl(PySocketSockObject *s)
     SOCKET_T fd;
     int res;
 
-    fd = s->sock_fd;
+    fd = get_sock_fd(s);
     if (fd != INVALID_SOCKET) {
-        s->sock_fd = INVALID_SOCKET;
+        set_sock_fd(s, INVALID_SOCKET);
 
         /* We do not want to retry upon EINTR: see
            http://lwn.net/Articles/576478/ and
@@ -3390,8 +3427,8 @@ _socket_socket_close_impl(PySocketSockObject *s)
 static PyObject *
 sock_detach(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
 {
-    SOCKET_T fd = s->sock_fd;
-    s->sock_fd = INVALID_SOCKET;
+    SOCKET_T fd = get_sock_fd(s);
+    set_sock_fd(s, INVALID_SOCKET);
     return PyLong_FromSocket_t(fd);
 }
 
@@ -3409,7 +3446,7 @@ sock_connect_impl(PySocketSockObject *s, void* Py_UNUSED(data))
     int err;
     socklen_t size = sizeof err;
 
-    if (getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, (void *)&err, &size)) {
+    if (getsockopt(get_sock_fd(s), SOL_SOCKET, SO_ERROR, (void *)&err, &size)) {
         /* getsockopt() failed */
         return 0;
     }
@@ -3443,7 +3480,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
     int res, err, wait_connect;
 
     Py_BEGIN_ALLOW_THREADS
-    res = connect(s->sock_fd, addr, addrlen);
+    res = connect(get_sock_fd(s), addr, addrlen);
     Py_END_ALLOW_THREADS
 
     if (!res) {
@@ -3573,7 +3610,7 @@ instead of raising an exception when an error occurs.");
 static PyObject *
 sock_fileno(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
 {
-    return PyLong_FromSocket_t(s->sock_fd);
+    return PyLong_FromSocket_t(get_sock_fd(s));
 }
 
 PyDoc_STRVAR(fileno_doc,
@@ -3596,11 +3633,11 @@ sock_getsockname(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
         return NULL;
     memset(&addrbuf, 0, addrlen);
     Py_BEGIN_ALLOW_THREADS
-    res = getsockname(s->sock_fd, SAS2SA(&addrbuf), &addrlen);
+    res = getsockname(get_sock_fd(s), SAS2SA(&addrbuf), &addrlen);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return s->errorhandler();
-    return makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen,
+    return makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen,
                         s->sock_proto);
 }
 
@@ -3628,11 +3665,11 @@ sock_getpeername(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
         return NULL;
     memset(&addrbuf, 0, addrlen);
     Py_BEGIN_ALLOW_THREADS
-    res = getpeername(s->sock_fd, SAS2SA(&addrbuf), &addrlen);
+    res = getpeername(get_sock_fd(s), SAS2SA(&addrbuf), &addrlen);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return s->errorhandler();
-    return makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen,
+    return makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen,
                         s->sock_proto);
 }
 
@@ -3664,7 +3701,7 @@ sock_listen(PySocketSockObject *s, PyObject *args)
      * (which doesn't make sense anyway) we force a minimum value of 0. */
     if (backlog < 0)
         backlog = 0;
-    res = listen(s->sock_fd, backlog);
+    res = listen(get_sock_fd(s), backlog);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return s->errorhandler();
@@ -3695,9 +3732,9 @@ sock_recv_impl(PySocketSockObject *s, void *data)
 #ifdef MS_WINDOWS
     if (ctx->len > INT_MAX)
         ctx->len = INT_MAX;
-    ctx->result = recv(s->sock_fd, ctx->cbuf, (int)ctx->len, ctx->flags);
+    ctx->result = recv(get_sock_fd(s), ctx->cbuf, (int)ctx->len, ctx->flags);
 #else
-    ctx->result = recv(s->sock_fd, ctx->cbuf, ctx->len, ctx->flags);
+    ctx->result = recv(get_sock_fd(s), ctx->cbuf, ctx->len, ctx->flags);
 #endif
     return (ctx->result >= 0);
 }
@@ -3866,10 +3903,10 @@ sock_recvfrom_impl(PySocketSockObject *s, void *data)
 #ifdef MS_WINDOWS
     if (ctx->len > INT_MAX)
         ctx->len = INT_MAX;
-    ctx->result = recvfrom(s->sock_fd, ctx->cbuf, (int)ctx->len, ctx->flags,
+    ctx->result = recvfrom(get_sock_fd(s), ctx->cbuf, (int)ctx->len, ctx->flags,
                            SAS2SA(ctx->addrbuf), ctx->addrlen);
 #else
-    ctx->result = recvfrom(s->sock_fd, ctx->cbuf, ctx->len, ctx->flags,
+    ctx->result = recvfrom(get_sock_fd(s), ctx->cbuf, ctx->len, ctx->flags,
                            SAS2SA(ctx->addrbuf), ctx->addrlen);
 #endif
     return (ctx->result >= 0);
@@ -3913,7 +3950,7 @@ sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags,
     if (sock_call(s, 0, sock_recvfrom_impl, &ctx) < 0)
         return -1;
 
-    *addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen,
+    *addr = makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen,
                          s->sock_proto);
     if (*addr == NULL)
         return -1;
@@ -4044,7 +4081,7 @@ sock_recvmsg_impl(PySocketSockObject *s, void *data)
 {
     struct sock_recvmsg *ctx = data;
 
-    ctx->result = recvmsg(s->sock_fd, ctx->msg, ctx->flags);
+    ctx->result = recvmsg(get_sock_fd(s), ctx->msg, ctx->flags);
     return  (ctx->result >= 0);
 }
 
@@ -4153,7 +4190,7 @@ sock_recvmsg_guts(PySocketSockObject *s, struct iovec *iov, int iovlen,
                            (*makeval)(ctx.result, makeval_data),
                            cmsg_list,
                            (int)msg.msg_flags,
-                           makesockaddr(s->sock_fd, SAS2SA(&addrbuf),
+                           makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf),
                                         ((msg.msg_namelen > addrbuflen) ?
                                          addrbuflen : msg.msg_namelen),
                                         s->sock_proto));
@@ -4372,9 +4409,9 @@ sock_send_impl(PySocketSockObject *s, void *data)
 #ifdef MS_WINDOWS
     if (ctx->len > INT_MAX)
         ctx->len = INT_MAX;
-    ctx->result = send(s->sock_fd, ctx->buf, (int)ctx->len, ctx->flags);
+    ctx->result = send(get_sock_fd(s), ctx->buf, (int)ctx->len, ctx->flags);
 #else
-    ctx->result = send(s->sock_fd, ctx->buf, ctx->len, ctx->flags);
+    ctx->result = send(get_sock_fd(s), ctx->buf, ctx->len, ctx->flags);
 #endif
     return (ctx->result >= 0);
 }
@@ -4511,10 +4548,10 @@ sock_sendto_impl(PySocketSockObject *s, void *data)
 #ifdef MS_WINDOWS
     if (ctx->len > INT_MAX)
         ctx->len = INT_MAX;
-    ctx->result = sendto(s->sock_fd, ctx->buf, (int)ctx->len, ctx->flags,
+    ctx->result = sendto(get_sock_fd(s), ctx->buf, (int)ctx->len, ctx->flags,
                          SAS2SA(ctx->addrbuf), ctx->addrlen);
 #else
-    ctx->result = sendto(s->sock_fd, ctx->buf, ctx->len, ctx->flags,
+    ctx->result = sendto(get_sock_fd(s), ctx->buf, ctx->len, ctx->flags,
                          SAS2SA(ctx->addrbuf), ctx->addrlen);
 #endif
     return (ctx->result >= 0);
@@ -4660,7 +4697,7 @@ sock_sendmsg_impl(PySocketSockObject *s, void *data)
 {
     struct sock_sendmsg *ctx = data;
 
-    ctx->result = sendmsg(s->sock_fd, ctx->msg, ctx->flags);
+    ctx->result = sendmsg(get_sock_fd(s), ctx->msg, ctx->flags);
     return (ctx->result >= 0);
 }
 
@@ -5048,7 +5085,7 @@ sock_shutdown(PySocketSockObject *s, PyObject *arg)
     if (how == -1 && PyErr_Occurred())
         return NULL;
     Py_BEGIN_ALLOW_THREADS
-    res = shutdown(s->sock_fd, how);
+    res = shutdown(get_sock_fd(s), how);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return s->errorhandler();
@@ -5078,7 +5115,7 @@ sock_ioctl(PySocketSockObject *s, PyObject *arg)
         unsigned int option = RCVALL_ON;
         if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option))
             return NULL;
-        if (WSAIoctl(s->sock_fd, cmd, &option, sizeof(option),
+        if (WSAIoctl(get_sock_fd(s), cmd, &option, sizeof(option),
                          NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
             return set_error();
         }
@@ -5088,7 +5125,7 @@ sock_ioctl(PySocketSockObject *s, PyObject *arg)
         if (!PyArg_ParseTuple(arg, "k(kkk):ioctl", &cmd,
                         &ka.onoff, &ka.keepalivetime, &ka.keepaliveinterval))
             return NULL;
-        if (WSAIoctl(s->sock_fd, cmd, &ka, sizeof(ka),
+        if (WSAIoctl(get_sock_fd(s), cmd, &ka, sizeof(ka),
                          NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
             return set_error();
         }
@@ -5098,7 +5135,7 @@ sock_ioctl(PySocketSockObject *s, PyObject *arg)
         unsigned int option;
         if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option))
             return NULL;
-        if (WSAIoctl(s->sock_fd, cmd, &option, sizeof(option),
+        if (WSAIoctl(get_sock_fd(s), cmd, &option, sizeof(option),
                          NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
             return set_error();
         }
@@ -5130,7 +5167,7 @@ sock_share(PySocketSockObject *s, PyObject *arg)
         return NULL;
 
     Py_BEGIN_ALLOW_THREADS
-    result = WSADuplicateSocketW(s->sock_fd, processId, &info);
+    result = WSADuplicateSocketW(get_sock_fd(s), processId, &info);
     Py_END_ALLOW_THREADS
     if (result == SOCKET_ERROR)
         return set_error();
@@ -5264,7 +5301,7 @@ sock_finalize(PySocketSockObject *s)
     /* Save the current exception, if any. */
     PyObject *exc = PyErr_GetRaisedException();
 
-    if (s->sock_fd != INVALID_SOCKET) {
+    if (get_sock_fd(s) != INVALID_SOCKET) {
         if (PyErr_ResourceWarning((PyObject *)s, 1, "unclosed %R", s)) {
             /* Spurious errors can appear at shutdown */
             if (PyErr_ExceptionMatches(PyExc_Warning)) {
@@ -5276,8 +5313,8 @@ sock_finalize(PySocketSockObject *s)
            to allow the logger to call socket methods like
            socket.getsockname(). If the socket is closed before, socket
            methods fails with the EBADF error. */
-        fd = s->sock_fd;
-        s->sock_fd = INVALID_SOCKET;
+        fd = get_sock_fd(s);
+        set_sock_fd(s, INVALID_SOCKET);
 
         /* We do not want to retry upon EINTR: see sock_close() */
         Py_BEGIN_ALLOW_THREADS
@@ -5314,11 +5351,11 @@ sock_repr(PySocketSockObject *s)
 {
     long sock_fd;
     /* On Windows, this test is needed because SOCKET_T is unsigned */
-    if (s->sock_fd == INVALID_SOCKET) {
+    if (get_sock_fd(s) == INVALID_SOCKET) {
         sock_fd = -1;
     }
 #if SIZEOF_SOCKET_T > SIZEOF_LONG
-    else if (s->sock_fd > LONG_MAX) {
+    else if (get_sock_fd(s) > LONG_MAX) {
         /* this can occur on Win64, and actually there is a special
            ugly printf formatter for decimal pointer length integer
            printing, only bother if necessary*/
@@ -5329,7 +5366,7 @@ sock_repr(PySocketSockObject *s)
     }
 #endif
     else
-        sock_fd = (long)s->sock_fd;
+        sock_fd = (long)get_sock_fd(s);
     return PyUnicode_FromFormat(
         "<socket object, fd=%ld, family=%d, type=%d, proto=%d>",
         sock_fd, s->sock_family,