Patch #1544279: Improve thread-safety of the socket module by moving
the sock_addr_t storage out of the socket object. Will backport to 2.5.
This commit is contained in:
parent
8609da9b17
commit
046c4d13be
|
@ -240,6 +240,9 @@ Library
|
|||
Extension Modules
|
||||
-----------------
|
||||
|
||||
- Patch #1544279: Improve thread-safety of the socket module by moving
|
||||
the sock_addr_t storage out of the socket object.
|
||||
|
||||
- Speed up function calls into the math module.
|
||||
|
||||
- Bug #1588217: don't parse "= " as a soft line break in binascii's
|
||||
|
|
|
@ -364,19 +364,16 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
|||
#define BTPROTO_RFCOMM BLUETOOTH_PROTO_RFCOMM
|
||||
#define sockaddr_l2 sockaddr_l2cap
|
||||
#define sockaddr_rc sockaddr_rfcomm
|
||||
#define _BT_SOCKADDR_MEMB(s, proto) &((s)->sock_addr)
|
||||
#define _BT_L2_MEMB(sa, memb) ((sa)->l2cap_##memb)
|
||||
#define _BT_RC_MEMB(sa, memb) ((sa)->rfcomm_##memb)
|
||||
#elif defined(__NetBSD__)
|
||||
#define sockaddr_l2 sockaddr_bt
|
||||
#define sockaddr_rc sockaddr_bt
|
||||
#define sockaddr_sco sockaddr_bt
|
||||
#define _BT_SOCKADDR_MEMB(s, proto) &((s)->sock_addr)
|
||||
#define _BT_L2_MEMB(sa, memb) ((sa)->bt_##memb)
|
||||
#define _BT_RC_MEMB(sa, memb) ((sa)->bt_##memb)
|
||||
#define _BT_SCO_MEMB(sa, memb) ((sa)->bt_##memb)
|
||||
#else
|
||||
#define _BT_SOCKADDR_MEMB(s, proto) (&((s)->sock_addr).bt_##proto)
|
||||
#define _BT_L2_MEMB(sa, memb) ((sa)->l2_##memb)
|
||||
#define _BT_RC_MEMB(sa, memb) ((sa)->rc_##memb)
|
||||
#define _BT_SCO_MEMB(sa, memb) ((sa)->sco_##memb)
|
||||
|
@ -388,6 +385,8 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
|||
#define SEGMENT_SIZE (32 * 1024 -1)
|
||||
#endif
|
||||
|
||||
#define SAS2SA(x) ((struct sockaddr *)(x))
|
||||
|
||||
/*
|
||||
* Constants for getnameinfo()
|
||||
*/
|
||||
|
@ -1174,7 +1173,7 @@ makesockaddr(int sockfd, struct sockaddr *addr, int addrlen, int proto)
|
|||
|
||||
static int
|
||||
getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||
struct sockaddr **addr_ret, int *len_ret)
|
||||
struct sockaddr *addr_ret, int *len_ret)
|
||||
{
|
||||
switch (s->sock_family) {
|
||||
|
||||
|
@ -1184,9 +1183,10 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
struct sockaddr_un* addr;
|
||||
char *path;
|
||||
int len;
|
||||
addr = (struct sockaddr_un*)&(s->sock_addr).un;
|
||||
if (!PyArg_Parse(args, "t#", &path, &len))
|
||||
return 0;
|
||||
|
||||
addr = (struct sockaddr_un*)addr_ret;
|
||||
#ifdef linux
|
||||
if (len > 0 && path[0] == 0) {
|
||||
/* Linux abstract namespace extension */
|
||||
|
@ -1209,7 +1209,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
}
|
||||
addr->sun_family = s->sock_family;
|
||||
memcpy(addr->sun_path, path, len);
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
#if defined(PYOS_OS2)
|
||||
*len_ret = sizeof(*addr);
|
||||
#else
|
||||
|
@ -1224,7 +1223,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
{
|
||||
struct sockaddr_nl* addr;
|
||||
int pid, groups;
|
||||
addr = (struct sockaddr_nl *)&(s->sock_addr).nl;
|
||||
addr = (struct sockaddr_nl *)addr_ret;
|
||||
if (!PyTuple_Check(args)) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
|
@ -1238,7 +1237,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
addr->nl_family = AF_NETLINK;
|
||||
addr->nl_pid = pid;
|
||||
addr->nl_groups = groups;
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof(*addr);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1249,7 +1247,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
struct sockaddr_in* addr;
|
||||
char *host;
|
||||
int port, result;
|
||||
addr=(struct sockaddr_in*)&(s->sock_addr).in;
|
||||
if (!PyTuple_Check(args)) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
|
@ -1261,6 +1258,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
if (!PyArg_ParseTuple(args, "eti:getsockaddrarg",
|
||||
"idna", &host, &port))
|
||||
return 0;
|
||||
addr=(struct sockaddr_in*)addr_ret;
|
||||
result = setipaddr(host, (struct sockaddr *)addr,
|
||||
sizeof(*addr), AF_INET);
|
||||
PyMem_Free(host);
|
||||
|
@ -1268,7 +1266,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
return 0;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = htons((short)port);
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof *addr;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1279,7 +1276,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
struct sockaddr_in6* addr;
|
||||
char *host;
|
||||
int port, flowinfo, scope_id, result;
|
||||
addr = (struct sockaddr_in6*)&(s->sock_addr).in6;
|
||||
flowinfo = scope_id = 0;
|
||||
if (!PyTuple_Check(args)) {
|
||||
PyErr_Format(
|
||||
|
@ -1294,6 +1290,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
&scope_id)) {
|
||||
return 0;
|
||||
}
|
||||
addr = (struct sockaddr_in6*)addr_ret;
|
||||
result = setipaddr(host, (struct sockaddr *)addr,
|
||||
sizeof(*addr), AF_INET6);
|
||||
PyMem_Free(host);
|
||||
|
@ -1303,7 +1300,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
addr->sin6_port = htons((short)port);
|
||||
addr->sin6_flowinfo = flowinfo;
|
||||
addr->sin6_scope_id = scope_id;
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof *addr;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1315,9 +1311,10 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
switch (s->sock_proto) {
|
||||
case BTPROTO_L2CAP:
|
||||
{
|
||||
struct sockaddr_l2 *addr = (struct sockaddr_l2 *) _BT_SOCKADDR_MEMB(s, l2);
|
||||
struct sockaddr_l2 *addr;
|
||||
char *straddr;
|
||||
|
||||
addr = (struct sockaddr_l2 *)addr_ret;
|
||||
_BT_L2_MEMB(addr, family) = AF_BLUETOOTH;
|
||||
if (!PyArg_ParseTuple(args, "si", &straddr,
|
||||
&_BT_L2_MEMB(addr, psm))) {
|
||||
|
@ -1328,15 +1325,15 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
if (setbdaddr(straddr, &_BT_L2_MEMB(addr, bdaddr)) < 0)
|
||||
return 0;
|
||||
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof *addr;
|
||||
return 1;
|
||||
}
|
||||
case BTPROTO_RFCOMM:
|
||||
{
|
||||
struct sockaddr_rc *addr = (struct sockaddr_rc *) _BT_SOCKADDR_MEMB(s, rc);
|
||||
struct sockaddr_rc *addr;
|
||||
char *straddr;
|
||||
|
||||
addr = (struct sockaddr_rc *)addr_ret;
|
||||
_BT_RC_MEMB(addr, family) = AF_BLUETOOTH;
|
||||
if (!PyArg_ParseTuple(args, "si", &straddr,
|
||||
&_BT_RC_MEMB(addr, channel))) {
|
||||
|
@ -1347,16 +1344,16 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
if (setbdaddr(straddr, &_BT_RC_MEMB(addr, bdaddr)) < 0)
|
||||
return 0;
|
||||
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof *addr;
|
||||
return 1;
|
||||
}
|
||||
#if !defined(__FreeBSD__)
|
||||
case BTPROTO_SCO:
|
||||
{
|
||||
struct sockaddr_sco *addr = (struct sockaddr_sco *) _BT_SOCKADDR_MEMB(s, sco);
|
||||
struct sockaddr_sco *addr;
|
||||
char *straddr;
|
||||
|
||||
addr = (struct sockaddr_sco *)addr_ret;
|
||||
_BT_SCO_MEMB(addr, family) = AF_BLUETOOTH;
|
||||
straddr = PyString_AsString(args);
|
||||
if (straddr == NULL) {
|
||||
|
@ -1367,7 +1364,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
if (setbdaddr(straddr, &_BT_SCO_MEMB(addr, bdaddr)) < 0)
|
||||
return 0;
|
||||
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof *addr;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1409,22 +1405,21 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
s->errorhandler();
|
||||
return 0;
|
||||
}
|
||||
addr = &(s->sock_addr.ll);
|
||||
addr->sll_family = AF_PACKET;
|
||||
addr->sll_protocol = htons((short)protoNumber);
|
||||
addr->sll_ifindex = ifr.ifr_ifindex;
|
||||
addr->sll_pkttype = pkttype;
|
||||
addr->sll_hatype = hatype;
|
||||
if (halen > 8) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Hardware address must be 8 bytes or less");
|
||||
return 0;
|
||||
}
|
||||
addr = (struct sockaddr_ll*)addr_ret;
|
||||
addr->sll_family = AF_PACKET;
|
||||
addr->sll_protocol = htons((short)protoNumber);
|
||||
addr->sll_ifindex = ifr.ifr_ifindex;
|
||||
addr->sll_pkttype = pkttype;
|
||||
addr->sll_hatype = hatype;
|
||||
if (halen != 0) {
|
||||
memcpy(&addr->sll_addr, haddr, halen);
|
||||
}
|
||||
addr->sll_halen = halen;
|
||||
*addr_ret = (struct sockaddr *) addr;
|
||||
*len_ret = sizeof *addr;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1551,8 +1546,7 @@ sock_accept(PySocketSockObject *s)
|
|||
Py_BEGIN_ALLOW_THREADS
|
||||
timeout = internal_select(s, 0);
|
||||
if (!timeout)
|
||||
newfd = accept(s->sock_fd, (struct sockaddr *) &addrbuf,
|
||||
&addrlen);
|
||||
newfd = accept(s->sock_fd, SAS2SA(&addrbuf), &addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (timeout == 1) {
|
||||
|
@ -1578,7 +1572,7 @@ sock_accept(PySocketSockObject *s)
|
|||
SOCKETCLOSE(newfd);
|
||||
goto finally;
|
||||
}
|
||||
addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf,
|
||||
addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf),
|
||||
addrlen, s->sock_proto);
|
||||
if (addr == NULL)
|
||||
goto finally;
|
||||
|
@ -1819,14 +1813,14 @@ string of that length; otherwise it is an integer.");
|
|||
static PyObject *
|
||||
sock_bind(PySocketSockObject *s, PyObject *addro)
|
||||
{
|
||||
struct sockaddr *addr;
|
||||
sock_addr_t addrbuf;
|
||||
int addrlen;
|
||||
int res;
|
||||
|
||||
if (!getsockaddrarg(s, addro, &addr, &addrlen))
|
||||
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
res = bind(s->sock_fd, addr, addrlen);
|
||||
res = bind(s->sock_fd, SAS2SA(&addrbuf), addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (res < 0)
|
||||
return s->errorhandler();
|
||||
|
@ -1952,16 +1946,16 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
|
|||
static PyObject *
|
||||
sock_connect(PySocketSockObject *s, PyObject *addro)
|
||||
{
|
||||
struct sockaddr *addr;
|
||||
sock_addr_t addrbuf;
|
||||
int addrlen;
|
||||
int res;
|
||||
int timeout;
|
||||
|
||||
if (!getsockaddrarg(s, addro, &addr, &addrlen))
|
||||
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
res = internal_connect(s, addr, addrlen, &timeout);
|
||||
res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (timeout == 1) {
|
||||
|
@ -1986,16 +1980,16 @@ is a pair (host, port).");
|
|||
static PyObject *
|
||||
sock_connect_ex(PySocketSockObject *s, PyObject *addro)
|
||||
{
|
||||
struct sockaddr *addr;
|
||||
sock_addr_t addrbuf;
|
||||
int addrlen;
|
||||
int res;
|
||||
int timeout;
|
||||
|
||||
if (!getsockaddrarg(s, addro, &addr, &addrlen))
|
||||
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
res = internal_connect(s, addr, addrlen, &timeout);
|
||||
res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
/* Signals are not errors (though they may raise exceptions). Adapted
|
||||
|
@ -2075,11 +2069,11 @@ sock_getsockname(PySocketSockObject *s)
|
|||
return NULL;
|
||||
memset(&addrbuf, 0, addrlen);
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
res = getsockname(s->sock_fd, (struct sockaddr *) &addrbuf, &addrlen);
|
||||
res = getsockname(s->sock_fd, SAS2SA(&addrbuf), &addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (res < 0)
|
||||
return s->errorhandler();
|
||||
return makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf, addrlen,
|
||||
return makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen,
|
||||
s->sock_proto);
|
||||
}
|
||||
|
||||
|
@ -2104,11 +2098,11 @@ sock_getpeername(PySocketSockObject *s)
|
|||
return NULL;
|
||||
memset(&addrbuf, 0, addrlen);
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
res = getpeername(s->sock_fd, (struct sockaddr *) &addrbuf, &addrlen);
|
||||
res = getpeername(s->sock_fd, SAS2SA(&addrbuf), &addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (res < 0)
|
||||
return s->errorhandler();
|
||||
return makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf, addrlen,
|
||||
return makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen,
|
||||
s->sock_proto);
|
||||
}
|
||||
|
||||
|
@ -2443,14 +2437,14 @@ sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, int len, int flags,
|
|||
#ifndef MS_WINDOWS
|
||||
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
|
||||
n = recvfrom(s->sock_fd, cbuf, len, flags,
|
||||
(struct sockaddr *) &addrbuf, &addrlen);
|
||||
SAS2SA(&addrbuf), &addrlen);
|
||||
#else
|
||||
n = recvfrom(s->sock_fd, cbuf, len, flags,
|
||||
(void *) &addrbuf, &addrlen);
|
||||
#endif
|
||||
#else
|
||||
n = recvfrom(s->sock_fd, cbuf, len, flags,
|
||||
(struct sockaddr *) &addrbuf, &addrlen);
|
||||
SAS2SA(&addrbuf), &addrlen);
|
||||
#endif
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
@ -2464,7 +2458,7 @@ sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, int len, int flags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!(*addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf,
|
||||
if (!(*addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf),
|
||||
addrlen, s->sock_proto)))
|
||||
return -1;
|
||||
|
||||
|
@ -2664,7 +2658,7 @@ sock_sendto(PySocketSockObject *s, PyObject *args)
|
|||
{
|
||||
PyObject *addro;
|
||||
char *buf;
|
||||
struct sockaddr *addr;
|
||||
sock_addr_t addrbuf;
|
||||
int addrlen, len, n = -1, flags, timeout;
|
||||
|
||||
flags = 0;
|
||||
|
@ -2675,16 +2669,16 @@ sock_sendto(PySocketSockObject *s, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!getsockaddrarg(s, addro, &addr, &addrlen))
|
||||
return NULL;
|
||||
|
||||
if (!IS_SELECTABLE(s))
|
||||
return select_error();
|
||||
|
||||
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
timeout = internal_select(s, 1);
|
||||
if (!timeout)
|
||||
n = sendto(s->sock_fd, buf, len, flags, addr, addrlen);
|
||||
n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (timeout == 1) {
|
||||
|
@ -2973,10 +2967,9 @@ socket_gethostbyname(PyObject *self, PyObject *args)
|
|||
|
||||
if (!PyArg_ParseTuple(args, "s:gethostbyname", &name))
|
||||
return NULL;
|
||||
if (setipaddr(name, (struct sockaddr *)&addrbuf, sizeof(addrbuf), AF_INET) < 0)
|
||||
if (setipaddr(name, SAS2SA(&addrbuf), sizeof(addrbuf), AF_INET) < 0)
|
||||
return NULL;
|
||||
return makeipaddr((struct sockaddr *)&addrbuf,
|
||||
sizeof(struct sockaddr_in));
|
||||
return makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(gethostbyname_doc,
|
||||
|
|
|
@ -114,7 +114,6 @@ typedef struct {
|
|||
int sock_family; /* Address family, e.g., AF_INET */
|
||||
int sock_type; /* Socket type, e.g., SOCK_STREAM */
|
||||
int sock_proto; /* Protocol type, usually 0 */
|
||||
sock_addr_t sock_addr; /* Socket address */
|
||||
PyObject *(*errorhandler)(void); /* Error handler; checks
|
||||
errno, returns NULL and
|
||||
sets a Python exception */
|
||||
|
|
Loading…
Reference in New Issue