]> granicus.if.org Git - python/commitdiff
Patch #1544279: Improve thread-safety of the socket module by moving
authorMartin v. Löwis <martin@v.loewis.de>
Sun, 3 Dec 2006 11:23:45 +0000 (11:23 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Sun, 3 Dec 2006 11:23:45 +0000 (11:23 +0000)
the sock_addr_t storage out of the socket object.
Will backport to 2.5.

Misc/NEWS
Modules/socketmodule.c
Modules/socketmodule.h

index 64ae13f00c99efe5484d5dee7f7dc8ccfcf6da2d..0ce50edfc54d745e9200fc0ed6c2988fc08c2137 100644 (file)
--- 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
index f03b34c057f8689683bba791bc53d9b06dbe704d..c9f0388a302c4cabcfbfb2df83650adc3f09bb00 100644 (file)
@@ -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,
index ae38c86cbc698a344e3aa0a0010c94972b54d2d6..84f2422f418283c57d5a82e473431982705e1f08 100644 (file)
@@ -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 */