gh-117657: Use critical section to make _socket.socket.close thread safe (GH-120490)

This commit is contained in:
AN Long 2024-07-01 22:38:30 +08:00 committed by GitHub
parent c7991cc287
commit 8a5176772c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 10 deletions

View File

@ -6,8 +6,35 @@ preserve
# include "pycore_gc.h" // PyGC_Head # include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID() # include "pycore_runtime.h" // _Py_ID()
#endif #endif
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() #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 static int
sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto,
PyObject *fdobj); PyObject *fdobj);
@ -259,4 +286,4 @@ exit:
#ifndef _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF #ifndef _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF
#define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF #define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF
#endif /* !defined(_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]*/

View 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 Set the file descriptor to -1 so operations tried subsequently
will surely fail. */ 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 * 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; SOCKET_T fd;
int res; int res;
@ -3357,11 +3368,6 @@ sock_close(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(sock_close_doc,
"close()\n\
\n\
Close the socket. It cannot be used after this call.");
static PyObject * static PyObject *
sock_detach(PySocketSockObject *s, PyObject *Py_UNUSED(ignored)) sock_detach(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
{ {
@ -5118,8 +5124,7 @@ static PyMethodDef sock_methods[] = {
{"bind", (PyCFunction)sock_bind, METH_O, {"bind", (PyCFunction)sock_bind, METH_O,
bind_doc}, bind_doc},
#endif #endif
{"close", (PyCFunction)sock_close, METH_NOARGS, _SOCKET_SOCKET_CLOSE_METHODDEF
sock_close_doc},
#ifdef HAVE_CONNECT #ifdef HAVE_CONNECT
{"connect", (PyCFunction)sock_connect, METH_O, {"connect", (PyCFunction)sock_connect, METH_O,
connect_doc}, connect_doc},

View File

@ -54,7 +54,6 @@ race_top:PyInterpreterState_ThreadHead
race_top:_PyObject_TryGetInstanceAttribute race_top:_PyObject_TryGetInstanceAttribute
race_top:PyThreadState_Next race_top:PyThreadState_Next
race_top:PyUnstable_InterpreterFrame_GetLine race_top:PyUnstable_InterpreterFrame_GetLine
race_top:sock_close
race_top:tstate_delete_common race_top:tstate_delete_common
race_top:tstate_is_freed race_top:tstate_is_freed
race_top:type_modified_unlocked race_top:type_modified_unlocked