summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2006-12-03 11:23:45 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2006-12-03 11:23:45 (GMT)
commit046c4d13beea45c2b89b7b80f2654dff5a38eac8 (patch)
treefa6ee440f5575b55f9af8948e1233bbf0ea44c4f
parent8609da9b17ef73a2fbd272fe665ca054f6383929 (diff)
downloadcpython-046c4d13beea45c2b89b7b80f2654dff5a38eac8.zip
cpython-046c4d13beea45c2b89b7b80f2654dff5a38eac8.tar.gz
cpython-046c4d13beea45c2b89b7b80f2654dff5a38eac8.tar.bz2
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.
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/socketmodule.c97
-rw-r--r--Modules/socketmodule.h1
3 files changed, 48 insertions, 53 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 64ae13f..0ce50ed 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index f03b34c..c9f0388 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -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,
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index ae38c86..84f2422 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -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 */