]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117657: Use critical section to make _socket.socket.close thread safe (GH-120490)
authorAN Long <aisk@users.noreply.github.com>
Mon, 1 Jul 2024 14:38:30 +0000 (22:38 +0800)
committerGitHub <noreply@github.com>
Mon, 1 Jul 2024 14:38:30 +0000 (16:38 +0200)
Modules/clinic/socketmodule.c.h
Modules/socketmodule.c
Tools/tsan/suppressions_free_threading.txt

index 3f4056efff2fec542f0ce48367d9708d4b6ae8ff..7b0a3f8d4b1cc61a8096b0903f0cf06330d0f873 100644 (file)
@@ -6,8 +6,35 @@ preserve
 #  include "pycore_gc.h"          // PyGC_Head
 #  include "pycore_runtime.h"     // _Py_ID()
 #endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
 
+PyDoc_STRVAR(_socket_socket_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"close()\n"
+"\n"
+"Close the socket.  It cannot be used after this call.");
+
+#define _SOCKET_SOCKET_CLOSE_METHODDEF    \
+    {"close", (PyCFunction)_socket_socket_close, METH_NOARGS, _socket_socket_close__doc__},
+
+static PyObject *
+_socket_socket_close_impl(PySocketSockObject *s);
+
+static PyObject *
+_socket_socket_close(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(s);
+    return_value = _socket_socket_close_impl(s);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
 static int
 sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto,
                   PyObject *fdobj);
@@ -259,4 +286,4 @@ exit:
 #ifndef _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF
     #define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF
 #endif /* !defined(_SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF) */
-/*[clinic end generated code: output=eb37b5d88a1e4661 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6037e47b012911c5 input=a9049054013a1b77]*/
index 6d161478be2d9dd72646f61493c710947183ee88..3ffdaa45f16ac7f870e50f5788b527c6a15f04e9 100644 (file)
@@ -3331,8 +3331,19 @@ sockets the address is a tuple (ifname, proto [,pkttype [,hatype [,addr]]])");
    Set the file descriptor to -1 so operations tried subsequently
    will surely fail. */
 
+/*[clinic input]
+@critical_section
+_socket.socket.close
+    self as s: self(type="PySocketSockObject *")
+
+close()
+
+Close the socket.  It cannot be used after this call.
+[clinic start generated code]*/
+
 static PyObject *
-sock_close(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
+_socket_socket_close_impl(PySocketSockObject *s)
+/*[clinic end generated code: output=038b2418e07f6f6c input=9839a261e05bcb97]*/
 {
     SOCKET_T fd;
     int res;
@@ -3357,11 +3368,6 @@ sock_close(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(sock_close_doc,
-"close()\n\
-\n\
-Close the socket.  It cannot be used after this call.");
-
 static PyObject *
 sock_detach(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
 {
@@ -5118,8 +5124,7 @@ static PyMethodDef sock_methods[] = {
     {"bind",              (PyCFunction)sock_bind, METH_O,
                       bind_doc},
 #endif
-    {"close",             (PyCFunction)sock_close, METH_NOARGS,
-                      sock_close_doc},
+    _SOCKET_SOCKET_CLOSE_METHODDEF
 #ifdef HAVE_CONNECT
     {"connect",           (PyCFunction)sock_connect, METH_O,
                       connect_doc},
index 2986efe6774157eb0ce0f436ee4981b1e11a906e..0e17237eaa331df6971d01c277ef0c5383712283 100644 (file)
@@ -54,7 +54,6 @@ race_top:PyInterpreterState_ThreadHead
 race_top:_PyObject_TryGetInstanceAttribute
 race_top:PyThreadState_Next
 race_top:PyUnstable_InterpreterFrame_GetLine
-race_top:sock_close
 race_top:tstate_delete_common
 race_top:tstate_is_freed
 race_top:type_modified_unlocked