diff options
Diffstat (limited to 'Modules/socketmodule.c')
| -rw-r--r-- | Modules/socketmodule.c | 1314 | 
1 files changed, 806 insertions, 508 deletions
| diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index b6f2bf53ab..7610b0c05d 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -121,7 +121,7 @@ getpeername() -- return remote address [*]\n\  getsockname() -- return local address\n\  getsockopt(level, optname[, buflen]) -- get socket options\n\  gettimeout() -- return timeout or None\n\ -listen(n) -- start listening for incoming connections\n\ +listen([n]) -- start listening for incoming connections\n\  recv(buflen[, flags]) -- receive data\n\  recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\  recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\ @@ -284,14 +284,15 @@ if_indextoname(index) -- return the corresponding interface name\n\  #  include <fcntl.h>  # endif +#if defined(_MSC_VER) && _MSC_VER >= 1800 +/* Provides the IsWindows7SP1OrGreater() function */ +#include <VersionHelpers.h>  #endif -#include <stddef.h> - -#ifndef offsetof -# define offsetof(type, member) ((size_t)(&((type *)0)->member))  #endif +#include <stddef.h> +  #ifndef O_NONBLOCK  # define O_NONBLOCK O_NDELAY  #endif @@ -459,7 +460,7 @@ static PyTypeObject sock_type;  #else  /* If there's no timeout left, we don't have to call select, so it's a safe,   * little white lie. */ -#define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0.0) +#define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0)  #endif  static PyObject* @@ -481,6 +482,19 @@ select_error(void)  #endif  #ifdef MS_WINDOWS +#  define GET_SOCK_ERROR WSAGetLastError() +#  define SET_SOCK_ERROR(err) WSASetLastError(err) +#  define SOCK_TIMEOUT_ERR WSAEWOULDBLOCK +#  define SOCK_INPROGRESS_ERR WSAEWOULDBLOCK +#else +#  define GET_SOCK_ERROR errno +#  define SET_SOCK_ERROR(err) do { errno = err; } while (0) +#  define SOCK_TIMEOUT_ERR EWOULDBLOCK +#  define SOCK_INPROGRESS_ERR EINPROGRESS +#endif + + +#ifdef MS_WINDOWS  /* Does WSASocket() support the WSA_FLAG_NO_HANDLE_INHERIT flag? */  static int support_wsa_no_inherit = -1;  #endif @@ -552,6 +566,9 @@ set_gaierror(int error)  static int  internal_setblocking(PySocketSockObject *s, int block)  { +#ifdef MS_WINDOWS +    u_long arg; +#endif  #if !defined(MS_WINDOWS) \      && !((defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)))      int delay_flag, new_delay_flag; @@ -578,8 +595,8 @@ internal_setblocking(PySocketSockObject *s, int block)          fcntl(s->sock_fd, F_SETFL, new_delay_flag);  #endif  #else /* MS_WINDOWS */ -    block = !block; -    ioctlsocket(s->sock_fd, FIONBIO, (u_long*)&block); +    arg = !block; +    ioctlsocket(s->sock_fd, FIONBIO, &arg);  #endif /* MS_WINDOWS */      Py_END_ALLOW_THREADS @@ -587,60 +604,79 @@ internal_setblocking(PySocketSockObject *s, int block)      return 1;  } -/* Do a select()/poll() on the socket, if necessary (sock_timeout > 0). -   The argument writing indicates the direction. -   This does not raise an exception; we'll let our caller do that -   after they've reacquired the interpreter lock. -   Returns 1 on timeout, -1 on error, 0 otherwise. */  static int -internal_select_ex(PySocketSockObject *s, int writing, double interval) +internal_select(PySocketSockObject *s, int writing, _PyTime_t interval, +                int connect)  {      int n; +#ifdef HAVE_POLL +    struct pollfd pollfd; +    _PyTime_t ms; +#else +    fd_set fds, efds; +    struct timeval tv, *tvp; +#endif -    /* Nothing to do unless we're in timeout mode (not non-blocking) */ -    if (s->sock_timeout <= 0.0) -        return 0; +#ifdef WITH_THREAD +    /* must be called with the GIL held */ +    assert(PyGILState_Check()); +#endif + +    /* Error condition is for output only */ +    assert(!(connect && !writing));      /* Guard against closed socket */      if (s->sock_fd < 0)          return 0; -    /* Handling this condition here simplifies the select loops */ -    if (interval < 0.0) -        return 1; -      /* Prefer poll, if available, since you can poll() any fd       * which can't be done with select(). */  #ifdef HAVE_POLL -    { -        struct pollfd pollfd; -        int timeout; +    pollfd.fd = s->sock_fd; +    pollfd.events = writing ? POLLOUT : POLLIN; +    if (connect) { +        /* On Windows, the socket becomes writable on connection success, +           but a connection failure is notified as an error. On POSIX, the +           socket becomes writable on connection success or on connection +           failure. */ +        pollfd.events |= POLLERR; +    } -        pollfd.fd = s->sock_fd; -        pollfd.events = writing ? POLLOUT : POLLIN; +    /* s->sock_timeout is in seconds, timeout in ms */ +    ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); +    assert(ms <= INT_MAX); -        /* s->sock_timeout is in seconds, timeout in ms */ -        timeout = (int)(interval * 1000 + 0.5); -        n = poll(&pollfd, 1, timeout); -    } +    Py_BEGIN_ALLOW_THREADS; +    n = poll(&pollfd, 1, (int)ms); +    Py_END_ALLOW_THREADS;  #else -    { -        /* Construct the arguments to select */ -        fd_set fds; -        struct timeval tv; -        tv.tv_sec = (int)interval; -        tv.tv_usec = (int)((interval - tv.tv_sec) * 1e6); -        FD_ZERO(&fds); -        FD_SET(s->sock_fd, &fds); - -        /* See if the socket is ready */ -        if (writing) -            n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), -                       NULL, &fds, NULL, &tv); -        else -            n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), -                       &fds, NULL, NULL, &tv); +    if (interval >= 0) { +        _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); +        tvp = &tv;      } +    else +        tvp = NULL; + +    FD_ZERO(&fds); +    FD_SET(s->sock_fd, &fds); +    FD_ZERO(&efds); +    if (connect) { +        /* On Windows, the socket becomes writable on connection success, +           but a connection failure is notified as an error. On POSIX, the +           socket becomes writable on connection success or on connection +           failure. */ +        FD_SET(s->sock_fd, &efds); +    } + +    /* See if the socket is ready */ +    Py_BEGIN_ALLOW_THREADS; +    if (writing) +        n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), +                   NULL, &fds, &efds, tvp); +    else +        n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), +                   &fds, NULL, &efds, tvp); +    Py_END_ALLOW_THREADS;  #endif      if (n < 0) @@ -650,56 +686,166 @@ internal_select_ex(PySocketSockObject *s, int writing, double interval)      return 0;  } +/* Call a socket function. + +   On error, raise an exception and return -1 if err is set, or fill err and +   return -1 otherwise. If a signal was received and the signal handler raised +   an exception, return -1, and set err to -1 if err is set. + +   On success, return 0, and set err to 0 if err is set. + +   If the socket has a timeout, wait until the socket is ready before calling +   the function: wait until the socket is writable if writing is nonzero, wait +   until the socket received data otherwise. + +   If the socket function is interrupted by a signal (failed with EINTR): retry +   the function, except if the signal handler raised an exception (PEP 475). + +   When the function is retried, recompute the timeout using a monotonic clock. + +   sock_call_ex() must be called with the GIL held. The socket function is +   called with the GIL released. */  static int -internal_select(PySocketSockObject *s, int writing) +sock_call_ex(PySocketSockObject *s, +             int writing, +             int (*sock_func) (PySocketSockObject *s, void *data), +             void *data, +             int connect, +             int *err, +             _PyTime_t timeout)  { -    return internal_select_ex(s, writing, s->sock_timeout); -} +    int has_timeout = (timeout > 0); +    _PyTime_t deadline = 0; +    int deadline_initialized = 0; +    int res; -/* -   Two macros for automatic retry of select() in case of false positives -   (for example, select() could indicate a socket is ready for reading -    but the data then discarded by the OS because of a wrong checksum). -   Here is an example of use: +    /* sock_call() must be called with the GIL held. */ +    assert(PyGILState_Check()); + +    /* outer loop to retry select() when select() is interrupted by a signal +       or to retry select()+sock_func() on false positive (see above) */ +    while (1) { +        /* For connect(), poll even for blocking socket. The connection +           runs asynchronously. */ +        if (has_timeout || connect) { +            if (has_timeout) { +                _PyTime_t interval; + +                if (deadline_initialized) { +                    /* recompute the timeout */ +                    interval = deadline - _PyTime_GetMonotonicClock(); +                } +                else { +                    deadline_initialized = 1; +                    deadline = _PyTime_GetMonotonicClock() + timeout; +                    interval = timeout; +                } -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS -    timeout = internal_select_ex(s, 0, interval); -    if (!timeout) -        outlen = recv(s->sock_fd, cbuf, len, flags); -    Py_END_ALLOW_THREADS -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); +                if (interval >= 0) +                    res = internal_select(s, writing, interval, connect); +                else +                    res = 1; +            } +            else { +                res = internal_select(s, writing, timeout, connect); +            } + +            if (res == -1) { +                if (err) +                    *err = GET_SOCK_ERROR; + +                if (CHECK_ERRNO(EINTR)) { +                    /* select() was interrupted by a signal */ +                    if (PyErr_CheckSignals()) { +                        if (err) +                            *err = -1; +                        return -1; +                    } + +                    /* retry select() */ +                    continue; +                } + +                /* select() failed */ +                s->errorhandler(); +                return -1; +            } + +            if (res == 1) { +                if (err) +                    *err = SOCK_TIMEOUT_ERR; +                else +                    PyErr_SetString(socket_timeout, "timed out"); +                return -1; +            } + +            /* the socket is ready */ +        } + +        /* inner loop to retry sock_func() when sock_func() is interrupted +           by a signal */ +        while (1) { +            Py_BEGIN_ALLOW_THREADS +            res = sock_func(s, data); +            Py_END_ALLOW_THREADS + +            if (res) { +                /* sock_func() succeeded */ +                if (err) +                    *err = 0; +                return 0; +            } + +            if (err) +                *err = GET_SOCK_ERROR; + +            if (!CHECK_ERRNO(EINTR)) +                break; + +            /* sock_func() was interrupted by a signal */ +            if (PyErr_CheckSignals()) { +                if (err) +                    *err = -1; +                return -1; +            } + +            /* retry sock_func() */ +        } + +        if (s->sock_timeout > 0 +            && (CHECK_ERRNO(EWOULDBLOCK) || CHECK_ERRNO(EAGAIN))) { +            /* False positive: sock_func() failed with EWOULDBLOCK or EAGAIN. + +               For example, select() could indicate a socket is ready for +               reading, but the data then discarded by the OS because of a +               wrong checksum. + +               Loop on select() to recheck for socket readyness. */ +            continue; +        } + +        /* sock_func() failed */ +        if (!err) +            s->errorhandler(); +        /* else: err was already set before */          return -1;      } -    END_SELECT_LOOP(s) -*/ +} + +static int +sock_call(PySocketSockObject *s, +          int writing, +          int (*func) (PySocketSockObject *s, void *data), +          void *data) +{ +    return sock_call_ex(s, writing, func, data, 0, NULL, s->sock_timeout); +} -#define BEGIN_SELECT_LOOP(s) \ -    { \ -        _PyTime_timeval now, deadline = {0, 0}; \ -        double interval = s->sock_timeout; \ -        int has_timeout = s->sock_timeout > 0.0; \ -        if (has_timeout) { \ -            _PyTime_gettimeofday(&now); \ -            deadline = now; \ -            _PyTime_ADD_SECONDS(deadline, s->sock_timeout); \ -        } \ -        while (1) { \ -            errno = 0; \ - -#define END_SELECT_LOOP(s) \ -            if (!has_timeout || \ -                (!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \ -                break; \ -            _PyTime_gettimeofday(&now); \ -            interval = _PyTime_INTERVAL(now, deadline); \ -        } \ -    } \  /* Initialize a new socket object. */ -static double defaulttimeout = -1.0; /* Default timeout for new sockets */ +/* Default timeout for new sockets */ +static _PyTime_t defaulttimeout = _PYTIME_FROMSECONDS(-1);  static void  init_sockobject(PySocketSockObject *s, @@ -713,12 +859,12 @@ init_sockobject(PySocketSockObject *s,      s->errorhandler = &set_error;  #ifdef SOCK_NONBLOCK      if (type & SOCK_NONBLOCK) -        s->sock_timeout = 0.0; +        s->sock_timeout = 0;      else  #endif      {          s->sock_timeout = defaulttimeout; -        if (defaulttimeout >= 0.0) +        if (defaulttimeout >= 0)              internal_setblocking(s, 0);      } @@ -1214,6 +1360,71 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)      }  } +/* Helper for getsockaddrarg: bypass IDNA for ASCII-only host names +   (in particular, numeric IP addresses). */ +struct maybe_idna { +    PyObject *obj; +    char *buf; +}; + +static void +idna_cleanup(struct maybe_idna *data) +{ +    Py_CLEAR(data->obj); +} + +static int +idna_converter(PyObject *obj, struct maybe_idna *data) +{ +    size_t len; +    PyObject *obj2, *obj3; +    if (obj == NULL) { +        idna_cleanup(data); +        return 1; +    } +    data->obj = NULL; +    len = -1; +    if (PyBytes_Check(obj)) { +        data->buf = PyBytes_AsString(obj); +        len = PyBytes_Size(obj); +    } +    else if (PyByteArray_Check(obj)) { +        data->buf = PyByteArray_AsString(obj); +        len = PyByteArray_Size(obj); +    } +    else if (PyUnicode_Check(obj) && PyUnicode_READY(obj) == 0 && PyUnicode_IS_COMPACT_ASCII(obj)) { +        data->buf = PyUnicode_DATA(obj); +        len = PyUnicode_GET_LENGTH(obj); +    } +    else { +        obj2 = PyUnicode_FromObject(obj); +        if (!obj2) { +            PyErr_Format(PyExc_TypeError, "string or unicode text buffer expected, not %s", +                         obj->ob_type->tp_name); +            return 0; +        } +        obj3 = PyUnicode_AsEncodedString(obj2, "idna", NULL); +        Py_DECREF(obj2); +        if (!obj3) { +            PyErr_SetString(PyExc_TypeError, "encoding of hostname failed"); +            return 0; +        } +        if (!PyBytes_Check(obj3)) { +            Py_DECREF(obj3); +            PyErr_SetString(PyExc_TypeError, "encoding of hostname failed to return bytes"); +            return 0; +        } +        data->obj = obj3; +        data->buf = PyBytes_AS_STRING(obj3); +        len = PyBytes_GET_SIZE(obj3); +    } +    if (strlen(data->buf) != len) { +        Py_CLEAR(data->obj); +        PyErr_SetString(PyExc_TypeError, "host name must not contain null character"); +        return 0; +    } +    return Py_CLEANUP_SUPPORTED; +}  /* Parse a socket address argument according to the socket object's     address family.  Return 1 if the address was in the proper format, @@ -1230,8 +1441,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,      case AF_UNIX:      {          struct sockaddr_un* addr; -        char *path; -        int len; +        Py_buffer path;          int retval = 0;          /* PEP 383.  Not using PyUnicode_FSConverter since we need to @@ -1242,14 +1452,17 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,          }          else              Py_INCREF(args); -        if (!PyArg_Parse(args, "y#", &path, &len)) -            goto unix_out; +        if (!PyArg_Parse(args, "y*", &path)) { +            Py_DECREF(args); +            return retval; +        } +        assert(path.len >= 0);          addr = (struct sockaddr_un*)addr_ret;  #ifdef linux -        if (len > 0 && path[0] == 0) { +        if (path.len > 0 && *(const char *)path.buf == 0) {              /* Linux abstract namespace extension */ -            if (len > sizeof addr->sun_path) { +            if ((size_t)path.len > sizeof addr->sun_path) {                  PyErr_SetString(PyExc_OSError,                                  "AF_UNIX path too long");                  goto unix_out; @@ -1259,18 +1472,19 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,  #endif /* linux */          {              /* regular NULL-terminated string */ -            if (len >= sizeof addr->sun_path) { +            if ((size_t)path.len >= sizeof addr->sun_path) {                  PyErr_SetString(PyExc_OSError,                                  "AF_UNIX path too long");                  goto unix_out;              } -            addr->sun_path[len] = 0; +            addr->sun_path[path.len] = 0;          }          addr->sun_family = s->sock_family; -        memcpy(addr->sun_path, path, len); -        *len_ret = len + offsetof(struct sockaddr_un, sun_path); +        memcpy(addr->sun_path, path.buf, path.len); +        *len_ret = path.len + offsetof(struct sockaddr_un, sun_path);          retval = 1;      unix_out: +        PyBuffer_Release(&path);          Py_DECREF(args);          return retval;      } @@ -1308,7 +1522,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,      case AF_INET:      {          struct sockaddr_in* addr; -        char *host; +        struct maybe_idna host = {NULL, NULL};          int port, result;          if (!PyTuple_Check(args)) {              PyErr_Format( @@ -1318,13 +1532,13 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,                  Py_TYPE(args)->tp_name);              return 0;          } -        if (!PyArg_ParseTuple(args, "eti:getsockaddrarg", -                              "idna", &host, &port)) +        if (!PyArg_ParseTuple(args, "O&i:getsockaddrarg", +                              idna_converter, &host, &port))              return 0;          addr=(struct sockaddr_in*)addr_ret; -        result = setipaddr(host, (struct sockaddr *)addr, +        result = setipaddr(host.buf, (struct sockaddr *)addr,                             sizeof(*addr),  AF_INET); -        PyMem_Free(host); +        idna_cleanup(&host);          if (result < 0)              return 0;          if (port < 0 || port > 0xffff) { @@ -1343,7 +1557,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,      case AF_INET6:      {          struct sockaddr_in6* addr; -        char *host; +        struct maybe_idna host = {NULL, NULL};          int port, result;          unsigned int flowinfo, scope_id;          flowinfo = scope_id = 0; @@ -1355,15 +1569,15 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,                  Py_TYPE(args)->tp_name);              return 0;          } -        if (!PyArg_ParseTuple(args, "eti|II", -                              "idna", &host, &port, &flowinfo, +        if (!PyArg_ParseTuple(args, "O&i|II", +                              idna_converter, &host, &port, &flowinfo,                                &scope_id)) {              return 0;          }          addr = (struct sockaddr_in6*)addr_ret; -        result = setipaddr(host, (struct sockaddr *)addr, +        result = setipaddr(host.buf, (struct sockaddr *)addr,                             sizeof(*addr), AF_INET6); -        PyMem_Free(host); +        idna_cleanup(&host);          if (result < 0)              return 0;          if (port < 0 || port > 0xffff) { @@ -1492,8 +1706,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,          int protoNumber;          int hatype = 0;          int pkttype = 0; -        char *haddr = NULL; -        unsigned int halen = 0; +        Py_buffer haddr = {NULL, NULL};          if (!PyTuple_Check(args)) {              PyErr_Format( @@ -1503,25 +1716,28 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,                  Py_TYPE(args)->tp_name);              return 0;          } -        if (!PyArg_ParseTuple(args, "si|iiy#", &interfaceName, +        if (!PyArg_ParseTuple(args, "si|iiy*", &interfaceName,                                &protoNumber, &pkttype, &hatype, -                              &haddr, &halen)) +                              &haddr))              return 0;          strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));          ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';          if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {              s->errorhandler(); +            PyBuffer_Release(&haddr);              return 0;          } -        if (halen > 8) { -          PyErr_SetString(PyExc_ValueError, -                          "Hardware address must be 8 bytes or less"); -          return 0; +        if (haddr.buf && haddr.len > 8) { +            PyErr_SetString(PyExc_ValueError, +                            "Hardware address must be 8 bytes or less"); +            PyBuffer_Release(&haddr); +            return 0;          }          if (protoNumber < 0 || protoNumber > 0xffff) {              PyErr_SetString(                  PyExc_OverflowError,                  "getsockaddrarg: protoNumber must be 0-65535."); +            PyBuffer_Release(&haddr);              return 0;          }          addr = (struct sockaddr_ll*)addr_ret; @@ -1530,11 +1746,14 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,          addr->sll_ifindex = ifr.ifr_ifindex;          addr->sll_pkttype = pkttype;          addr->sll_hatype = hatype; -        if (halen != 0) { -          memcpy(&addr->sll_addr, haddr, halen); +        if (haddr.buf) { +            memcpy(&addr->sll_addr, haddr.buf, haddr.len); +            addr->sll_halen = haddr.len;          } -        addr->sll_halen = halen; +        else +            addr->sll_halen = 0;          *len_ret = sizeof *addr; +        PyBuffer_Release(&haddr);          return 1;      }  #endif @@ -1611,7 +1830,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,              if (len == 0) {                  ifr.ifr_ifindex = 0; -            } else if (len < sizeof(ifr.ifr_name)) { +            } else if ((size_t)len < sizeof(ifr.ifr_name)) {                  strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name));                  ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';                  if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) { @@ -1661,7 +1880,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,                      return 0;                  } -                if (PyBytes_GET_SIZE(ctl_name) > sizeof(info.ctl_name)) { +                if (PyBytes_GET_SIZE(ctl_name) > (Py_ssize_t)sizeof(info.ctl_name)) {                      PyErr_SetString(PyExc_ValueError,                                      "provided string is too long");                      Py_DECREF(ctl_name); @@ -1896,8 +2115,15 @@ cmsg_min_space(struct msghdr *msg, struct cmsghdr *cmsgh, size_t space)      #pragma clang diagnostic push      #pragma clang diagnostic ignored "-Wtautological-compare"      #endif +    #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))) +    #pragma GCC diagnostic push +    #pragma GCC diagnostic ignored "-Wtype-limits" +    #endif      if (msg->msg_controllen < 0)          return 0; +    #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))) +    #pragma GCC diagnostic pop +    #endif      #ifdef __clang__      #pragma clang diagnostic pop      #endif @@ -1955,22 +2181,51 @@ get_cmsg_data_len(struct msghdr *msg, struct cmsghdr *cmsgh, size_t *data_len)  #endif    /* CMSG_LEN */ +struct sock_accept { +    socklen_t *addrlen; +    sock_addr_t *addrbuf; +    SOCKET_T result; +}; + +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) +/* accept4() is available on Linux 2.6.28+ and glibc 2.10 */ +static int accept4_works = -1; +#endif + +static int +sock_accept_impl(PySocketSockObject *s, void *data) +{ +    struct sock_accept *ctx = data; + +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) +    if (accept4_works != 0) { +        ctx->result = accept4(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen, +                              SOCK_CLOEXEC); +        if (ctx->result == INVALID_SOCKET && accept4_works == -1) { +            /* On Linux older than 2.6.28, accept4() fails with ENOSYS */ +            accept4_works = (errno != ENOSYS); +        } +    } +    if (accept4_works == 0) +        ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen); +#else +    ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen); +#endif +    return (ctx->result >= 0); +} +  /* s._accept() -> (fd, address) */  static PyObject *  sock_accept(PySocketSockObject *s)  {      sock_addr_t addrbuf; -    SOCKET_T newfd = INVALID_SOCKET; +    SOCKET_T newfd;      socklen_t addrlen;      PyObject *sock = NULL;      PyObject *addr = NULL;      PyObject *res = NULL; -    int timeout; -#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) -    /* accept4() is available on Linux 2.6.28+ and glibc 2.10 */ -    static int accept4_works = -1; -#endif +    struct sock_accept ctx;      if (!getsockaddrlen(s, &addrlen))          return NULL; @@ -1979,36 +2234,11 @@ sock_accept(PySocketSockObject *s)      if (!IS_SELECTABLE(s))          return select_error(); -    BEGIN_SELECT_LOOP(s) - -    Py_BEGIN_ALLOW_THREADS -    timeout = internal_select_ex(s, 0, interval); -    if (!timeout) { -#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) -        if (accept4_works != 0) { -            newfd = accept4(s->sock_fd, SAS2SA(&addrbuf), &addrlen, -                            SOCK_CLOEXEC); -            if (newfd == INVALID_SOCKET && accept4_works == -1) { -                /* On Linux older than 2.6.28, accept4() fails with ENOSYS */ -                accept4_works = (errno != ENOSYS); -            } -        } -        if (accept4_works == 0) -            newfd = accept(s->sock_fd, SAS2SA(&addrbuf), &addrlen); -#else -        newfd = accept(s->sock_fd, SAS2SA(&addrbuf), &addrlen); -#endif -    } -    Py_END_ALLOW_THREADS - -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); +    ctx.addrlen = &addrlen; +    ctx.addrbuf = &addrbuf; +    if (sock_call(s, 0, sock_accept_impl, &ctx) < 0)          return NULL; -    } -    END_SELECT_LOOP(s) - -    if (newfd == INVALID_SOCKET) -        return s->errorhandler(); +    newfd = ctx.result;  #ifdef MS_WINDOWS      if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { @@ -2069,7 +2299,7 @@ sock_setblocking(PySocketSockObject *s, PyObject *arg)      if (block == -1 && PyErr_Occurred())          return NULL; -    s->sock_timeout = block ? -1.0 : 0.0; +    s->sock_timeout = _PyTime_FromSeconds(block ? -1 : 0);      internal_setblocking(s, block);      Py_INCREF(Py_None); @@ -2083,6 +2313,47 @@ Set the socket to blocking (flag is true) or non-blocking (false).\n\  setblocking(True) is equivalent to settimeout(None);\n\  setblocking(False) is equivalent to settimeout(0.0)."); +static int +socket_parse_timeout(_PyTime_t *timeout, PyObject *timeout_obj) +{ +#ifdef MS_WINDOWS +    struct timeval tv; +#endif +#ifndef HAVE_POLL +    _PyTime_t ms; +#endif +    int overflow = 0; + +    if (timeout_obj == Py_None) { +        *timeout = _PyTime_FromSeconds(-1); +        return 0; +    } + +    if (_PyTime_FromSecondsObject(timeout, +                                  timeout_obj, _PyTime_ROUND_CEILING) < 0) +        return -1; + +    if (*timeout < 0) { +        PyErr_SetString(PyExc_ValueError, "Timeout value out of range"); +        return -1; +    } + +#ifdef MS_WINDOWS +    overflow |= (_PyTime_AsTimeval(*timeout, &tv, _PyTime_ROUND_CEILING) < 0); +#endif +#ifndef HAVE_POLL +    ms = _PyTime_AsMilliseconds(*timeout, _PyTime_ROUND_CEILING); +    overflow |= (ms > INT_MAX); +#endif +    if (overflow) { +        PyErr_SetString(PyExc_OverflowError, +                        "timeout doesn't fit into C timeval"); +        return -1; +    } + +    return 0; +} +  /* s.settimeout(timeout) method.  Argument:     None -- no timeout, blocking mode; same as setblocking(True)     0.0  -- non-blocking mode; same as setblocking(False) @@ -2092,22 +2363,13 @@ setblocking(False) is equivalent to settimeout(0.0).");  static PyObject *  sock_settimeout(PySocketSockObject *s, PyObject *arg)  { -    double timeout; +    _PyTime_t timeout; -    if (arg == Py_None) -        timeout = -1.0; -    else { -        timeout = PyFloat_AsDouble(arg); -        if (timeout < 0.0) { -            if (!PyErr_Occurred()) -                PyErr_SetString(PyExc_ValueError, -                                "Timeout value out of range"); -            return NULL; -        } -    } +    if (socket_parse_timeout(&timeout, arg) < 0) +        return NULL;      s->sock_timeout = timeout; -    internal_setblocking(s, timeout < 0.0); +    internal_setblocking(s, timeout < 0);      Py_INCREF(Py_None);      return Py_None; @@ -2126,12 +2388,14 @@ Setting a timeout of zero is the same as setblocking(0).");  static PyObject *  sock_gettimeout(PySocketSockObject *s)  { -    if (s->sock_timeout < 0.0) { +    if (s->sock_timeout < 0) {          Py_INCREF(Py_None);          return Py_None;      } -    else -        return PyFloat_FromDouble(s->sock_timeout); +    else { +        double seconds = _PyTime_AsSecondsDouble(s->sock_timeout); +        return PyFloat_FromDouble(seconds); +    }  }  PyDoc_STRVAR(gettimeout_doc, @@ -2152,22 +2416,22 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)      int level;      int optname;      int res; -    char *buf; -    int buflen; +    Py_buffer optval;      int flag;      if (PyArg_ParseTuple(args, "iii:setsockopt",                           &level, &optname, &flag)) { -        buf = (char *) &flag; -        buflen = sizeof flag; +        res = setsockopt(s->sock_fd, level, optname, +                         (char*)&flag, sizeof flag);      }      else {          PyErr_Clear(); -        if (!PyArg_ParseTuple(args, "iiy#:setsockopt", -                              &level, &optname, &buf, &buflen)) +        if (!PyArg_ParseTuple(args, "iiy*:setsockopt", +                              &level, &optname, &optval))              return NULL; +        res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len); +        PyBuffer_Release(&optval);      } -    res = setsockopt(s->sock_fd, level, optname, (void *)buf, buflen);      if (res < 0)          return s->errorhandler();      Py_INCREF(Py_None); @@ -2271,6 +2535,10 @@ sock_close(PySocketSockObject *s)  {      SOCKET_T fd; +    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ +     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html +     * for more details. +     */      if ((fd = s->sock_fd) != -1) {          s->sock_fd = -1;          Py_BEGIN_ALLOW_THREADS @@ -2302,92 +2570,90 @@ The object cannot be used after this call, but the file descriptor\n\  can be reused for other purposes.  The file descriptor is returned.");  static int +sock_connect_impl(PySocketSockObject *s, void* Py_UNUSED(data)) +{ +    int err; +    socklen_t size = sizeof err; + +    if (getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, (void *)&err, &size)) { +        /* getsockopt() failed */ +        return 0; +    } + +    if (err == EISCONN) +        return 1; +    if (err != 0) { +        /* sock_call_ex() uses GET_SOCK_ERROR() to get the error code */ +        SET_SOCK_ERROR(err); +        return 0; +    } +    return 1; +} + +static int  internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, -                 int *timeoutp) +                 int raise)  { -    int res, timeout; +    int res, err, wait_connect; -    timeout = 0; +    Py_BEGIN_ALLOW_THREADS      res = connect(s->sock_fd, addr, addrlen); +    Py_END_ALLOW_THREADS -#ifdef MS_WINDOWS - -    if (s->sock_timeout > 0.0) { -        if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK && -            IS_SELECTABLE(s)) { -            /* This is a mess.  Best solution: trust select */ -            fd_set fds; -            fd_set fds_exc; -            struct timeval tv; -            tv.tv_sec = (int)s->sock_timeout; -            tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); -            FD_ZERO(&fds); -            FD_SET(s->sock_fd, &fds); -            FD_ZERO(&fds_exc); -            FD_SET(s->sock_fd, &fds_exc); -            res = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), -                         NULL, &fds, &fds_exc, &tv); -            if (res == 0) { -                res = WSAEWOULDBLOCK; -                timeout = 1; -            } else if (res > 0) { -                if (FD_ISSET(s->sock_fd, &fds)) -                    /* The socket is in the writable set - this -                       means connected */ -                    res = 0; -                else { -                    /* As per MS docs, we need to call getsockopt() -                       to get the underlying error */ -                    int res_size = sizeof res; -                    /* It must be in the exception set */ -                    assert(FD_ISSET(s->sock_fd, &fds_exc)); -                    if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, -                                        (char *)&res, &res_size)) -                        /* getsockopt also clears WSAGetLastError, -                           so reset it back. */ -                        WSASetLastError(res); -                    else -                        res = WSAGetLastError(); -                } -            } -            /* else if (res < 0) an error occurred */ -        } +    if (!res) { +        /* connect() succeeded, the socket is connected */ +        return 0;      } -    if (res < 0) -        res = WSAGetLastError(); +    /* connect() failed */ -#else +    /* save error, PyErr_CheckSignals() can replace it */ +    err = GET_SOCK_ERROR; +    if (CHECK_ERRNO(EINTR)) { +        if (PyErr_CheckSignals()) +            return -1; -    if (s->sock_timeout > 0.0) { -        if (res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) { -            timeout = internal_select(s, 1); -            if (timeout == 0) { -                /* Bug #1019808: in case of an EINPROGRESS, -                   use getsockopt(SO_ERROR) to get the real -                   error. */ -                socklen_t res_size = sizeof res; -                (void)getsockopt(s->sock_fd, SOL_SOCKET, -                                 SO_ERROR, &res, &res_size); -                if (res == EISCONN) -                    res = 0; -                errno = res; -            } -            else if (timeout == -1) { -                res = errno;            /* had error */ -            } -            else -                res = EWOULDBLOCK;                      /* timed out */ -        } -    } +        /* Issue #23618: when connect() fails with EINTR, the connection is +           running asynchronously. -    if (res < 0) -        res = errno; +           If the socket is blocking or has a timeout, wait until the +           connection completes, fails or timed out using select(), and then +           get the connection status using getsockopt(SO_ERROR). -#endif -    *timeoutp = timeout; +           If the socket is non-blocking, raise InterruptedError. The caller is +           responsible to wait until the connection completes, fails or timed +           out (it's the case in asyncio for example). */ +        wait_connect = (s->sock_timeout != 0 && IS_SELECTABLE(s)); +    } +    else { +        wait_connect = (s->sock_timeout > 0 && err == SOCK_INPROGRESS_ERR +                        && IS_SELECTABLE(s)); +    } -    return res; +    if (!wait_connect) { +        if (raise) { +            /* restore error, maybe replaced by PyErr_CheckSignals() */ +            SET_SOCK_ERROR(err); +            s->errorhandler(); +            return -1; +        } +        else +            return err; +    } + +    if (raise) { +        /* socket.connect() raises an exception on error */ +        if (sock_call_ex(s, 1, sock_connect_impl, NULL, +                         1, NULL, s->sock_timeout) < 0) +            return -1; +    } +    else { +        /* socket.connect_ex() returns the error code on error */ +        if (sock_call_ex(s, 1, sock_connect_impl, NULL, +                         1, &err, s->sock_timeout) < 0) +            return err; +    } +    return 0;  }  /* s.connect(sockaddr) method */ @@ -2398,23 +2664,15 @@ sock_connect(PySocketSockObject *s, PyObject *addro)      sock_addr_t addrbuf;      int addrlen;      int res; -    int timeout;      if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))          return NULL; -    Py_BEGIN_ALLOW_THREADS -    res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout); -    Py_END_ALLOW_THREADS - -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); +    res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1); +    if (res < 0)          return NULL; -    } -    if (res != 0) -        return s->errorhandler(); -    Py_INCREF(Py_None); -    return Py_None; + +    Py_RETURN_NONE;  }  PyDoc_STRVAR(connect_doc, @@ -2432,21 +2690,13 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro)      sock_addr_t addrbuf;      int addrlen;      int res; -    int timeout;      if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))          return NULL; -    Py_BEGIN_ALLOW_THREADS -    res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout); -    Py_END_ALLOW_THREADS - -    /* Signals are not errors (though they may raise exceptions).  Adapted -       from PyErr_SetFromErrnoWithFilenameObject(). */ -#ifdef EINTR -    if (res == EINTR && PyErr_CheckSignals()) +    res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0); +    if (res < 0)          return NULL; -#endif      return PyLong_FromLong((long) res);  } @@ -2534,14 +2784,16 @@ info is a pair (hostaddr, port).");  /* s.listen(n) method */  static PyObject * -sock_listen(PySocketSockObject *s, PyObject *arg) +sock_listen(PySocketSockObject *s, PyObject *args)  { -    int backlog; +    /* We try to choose a default backlog high enough to avoid connection drops +     * for common workloads, yet not too high to limit resource usage. */ +    int backlog = Py_MIN(SOMAXCONN, 128);      int res; -    backlog = _PyLong_AsInt(arg); -    if (backlog == -1 && PyErr_Occurred()) +    if (!PyArg_ParseTuple(args, "|i:listen", &backlog))          return NULL; +      Py_BEGIN_ALLOW_THREADS      /* To avoid problems on systems that don't allow a negative backlog       * (which doesn't make sense anyway) we force a minimum value of 0. */ @@ -2556,12 +2808,34 @@ sock_listen(PySocketSockObject *s, PyObject *arg)  }  PyDoc_STRVAR(listen_doc, -"listen(backlog)\n\ +"listen([backlog])\n\  \n\ -Enable a server to accept connections.  The backlog argument must be at\n\ -least 0 (if it is lower, it is set to 0); it specifies the number of\n\ +Enable a server to accept connections.  If backlog is specified, it must be\n\ +at least 0 (if it is lower, it is set to 0); it specifies the number of\n\  unaccepted connections that the system will allow before refusing new\n\ -connections."); +connections. If not specified, a default reasonable value is chosen."); + +struct sock_recv { +    char *cbuf; +    Py_ssize_t len; +    int flags; +    Py_ssize_t result; +}; + +static int +sock_recv_impl(PySocketSockObject *s, void *data) +{ +    struct sock_recv *ctx = data; + +#ifdef MS_WINDOWS +    if (ctx->len > INT_MAX) +        ctx->len = INT_MAX; +    ctx->result = recv(s->sock_fd, ctx->cbuf, (int)ctx->len, ctx->flags); +#else +    ctx->result = recv(s->sock_fd, ctx->cbuf, ctx->len, ctx->flags); +#endif +    return (ctx->result >= 0); +}  /* @@ -2576,8 +2850,7 @@ connections.");  static Py_ssize_t  sock_recv_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags)  { -    Py_ssize_t outlen = -1; -    int timeout; +    struct sock_recv ctx;      if (!IS_SELECTABLE(s)) {          select_error(); @@ -2588,32 +2861,13 @@ sock_recv_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags)          return 0;      } -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS -    timeout = internal_select_ex(s, 0, interval); -    if (!timeout) { -#ifdef MS_WINDOWS -        if (len > INT_MAX) -            len = INT_MAX; -        outlen = recv(s->sock_fd, cbuf, (int)len, flags); -#else -        outlen = recv(s->sock_fd, cbuf, len, flags); -#endif -    } -    Py_END_ALLOW_THREADS - -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); -        return -1; -    } -    END_SELECT_LOOP(s) -    if (outlen < 0) { -        /* Note: the call to errorhandler() ALWAYS indirectly returned -           NULL, so ignore its return value */ -        s->errorhandler(); +    ctx.cbuf = cbuf; +    ctx.len = len; +    ctx.flags = flags; +    if (sock_call(s, 0, sock_recv_impl, &ctx) < 0)          return -1; -    } -    return outlen; + +    return ctx.result;  } @@ -2727,6 +2981,34 @@ is not specified (or 0), receive up to the size available in the given buffer.\n  \n\  See recv() for documentation about the flags."); +struct sock_recvfrom { +    char* cbuf; +    Py_ssize_t len; +    int flags; +    socklen_t *addrlen; +    sock_addr_t *addrbuf; +    Py_ssize_t result; +}; + +static int +sock_recvfrom_impl(PySocketSockObject *s, void *data) +{ +    struct sock_recvfrom *ctx = data; + +    memset(ctx->addrbuf, 0, *ctx->addrlen); + +#ifdef MS_WINDOWS +    if (ctx->len > INT_MAX) +        ctx->len = INT_MAX; +    ctx->result = recvfrom(s->sock_fd, ctx->cbuf, (int)ctx->len, ctx->flags, +                           SAS2SA(ctx->addrbuf), ctx->addrlen); +#else +    ctx->result = recvfrom(s->sock_fd, ctx->cbuf, ctx->len, ctx->flags, +                           SAS2SA(ctx->addrbuf), ctx->addrlen); +#endif +    return (ctx->result >= 0); +} +  /*   * This is the guts of the recvfrom() and recvfrom_into() methods, which reads @@ -2744,9 +3026,8 @@ sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags,                     PyObject** addr)  {      sock_addr_t addrbuf; -    int timeout; -    Py_ssize_t n = -1;      socklen_t addrlen; +    struct sock_recvfrom ctx;      *addr = NULL; @@ -2758,38 +3039,20 @@ sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags,          return -1;      } -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS -    memset(&addrbuf, 0, addrlen); -    timeout = internal_select_ex(s, 0, interval); -    if (!timeout) { -#ifdef MS_WINDOWS -        if (len > INT_MAX) -            len = INT_MAX; -        n = recvfrom(s->sock_fd, cbuf, (int)len, flags, -                     (void *) &addrbuf, &addrlen); -#else -        n = recvfrom(s->sock_fd, cbuf, len, flags, -                     SAS2SA(&addrbuf), &addrlen); -#endif -    } -    Py_END_ALLOW_THREADS - -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); +    ctx.cbuf = cbuf; +    ctx.len = len; +    ctx.flags = flags; +    ctx.addrbuf = &addrbuf; +    ctx.addrlen = &addrlen; +    if (sock_call(s, 0, sock_recvfrom_impl, &ctx) < 0)          return -1; -    } -    END_SELECT_LOOP(s) -    if (n < 0) { -        s->errorhandler(); -        return -1; -    } -    if (!(*addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf), -                               addrlen, s->sock_proto))) +    *addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen, +                         s->sock_proto); +    if (*addr == NULL)          return -1; -    return n; +    return ctx.result;  }  /* s.recvfrom(nbytes [,flags]) method */ @@ -2900,10 +3163,24 @@ PyDoc_STRVAR(recvfrom_into_doc,  \n\  Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info."); -  /* The sendmsg() and recvmsg[_into]() methods require a working     CMSG_LEN().  See the comment near get_CMSG_LEN(). */  #ifdef CMSG_LEN +struct sock_recvmsg { +    struct msghdr *msg; +    int flags; +    ssize_t result; +}; + +static int +sock_recvmsg_impl(PySocketSockObject *s, void *data) +{ +    struct sock_recvmsg *ctx = data; + +    ctx->result = recvmsg(s->sock_fd, ctx->msg, ctx->flags); +    return  (ctx->result >= 0); +} +  /*   * Call recvmsg() with the supplied iovec structures, flags, and   * ancillary data buffer size (controllen).  Returns the tuple return @@ -2919,8 +3196,6 @@ sock_recvmsg_guts(PySocketSockObject *s, struct iovec *iov, int iovlen,                    int flags, Py_ssize_t controllen,                    PyObject *(*makeval)(ssize_t, void *), void *makeval_data)  { -    ssize_t bytes_received = -1; -    int timeout;      sock_addr_t addrbuf;      socklen_t addrbuflen;      struct msghdr msg = {0}; @@ -2929,6 +3204,7 @@ sock_recvmsg_guts(PySocketSockObject *s, struct iovec *iov, int iovlen,      struct cmsghdr *cmsgh;      size_t cmsgdatalen = 0;      int cmsg_status; +    struct sock_recvmsg ctx;      /* XXX: POSIX says that msg_name and msg_namelen "shall be         ignored" when the socket is connected (Linux fills them in @@ -2955,28 +3231,17 @@ sock_recvmsg_guts(PySocketSockObject *s, struct iovec *iov, int iovlen,          goto finally;      } -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS;      msg.msg_name = SAS2SA(&addrbuf);      msg.msg_namelen = addrbuflen;      msg.msg_iov = iov;      msg.msg_iovlen = iovlen;      msg.msg_control = controlbuf;      msg.msg_controllen = controllen; -    timeout = internal_select_ex(s, 0, interval); -    if (!timeout) -        bytes_received = recvmsg(s->sock_fd, &msg, flags); -    Py_END_ALLOW_THREADS; -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); -        goto finally; -    } -    END_SELECT_LOOP(s) -    if (bytes_received < 0) { -        s->errorhandler(); +    ctx.msg = &msg; +    ctx.flags = flags; +    if (sock_call(s, 0, sock_recvmsg_impl, &ctx) < 0)          goto finally; -    }      /* Make list of (level, type, data) tuples from control messages. */      if ((cmsg_list = PyList_New(0)) == NULL) @@ -3018,7 +3283,7 @@ sock_recvmsg_guts(PySocketSockObject *s, struct iovec *iov, int iovlen,      }      retval = Py_BuildValue("NOiN", -                           (*makeval)(bytes_received, makeval_data), +                           (*makeval)(ctx.result, makeval_data),                             cmsg_list,                             (int)msg.msg_flags,                             makesockaddr(s->sock_fd, SAS2SA(&addrbuf), @@ -3226,15 +3491,36 @@ SCM_RIGHTS mechanism.");  #endif    /* CMSG_LEN */ +struct sock_send { +    char *buf; +    Py_ssize_t len; +    int flags; +    Py_ssize_t result; +}; + +static int +sock_send_impl(PySocketSockObject *s, void *data) +{ +    struct sock_send *ctx = data; + +#ifdef MS_WINDOWS +    if (ctx->len > INT_MAX) +        ctx->len = INT_MAX; +    ctx->result = send(s->sock_fd, ctx->buf, (int)ctx->len, ctx->flags); +#else +    ctx->result = send(s->sock_fd, ctx->buf, ctx->len, ctx->flags); +#endif +    return (ctx->result >= 0); +} +  /* s.send(data [,flags]) method */  static PyObject *  sock_send(PySocketSockObject *s, PyObject *args)  { -    char *buf; -    Py_ssize_t len, n = -1; -    int flags = 0, timeout; +    int flags = 0;      Py_buffer pbuf; +    struct sock_send ctx;      if (!PyArg_ParseTuple(args, "y*|i:send", &pbuf, &flags))          return NULL; @@ -3243,33 +3529,16 @@ sock_send(PySocketSockObject *s, PyObject *args)          PyBuffer_Release(&pbuf);          return select_error();      } -    buf = pbuf.buf; -    len = pbuf.len; - -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS -    timeout = internal_select_ex(s, 1, interval); -    if (!timeout) { -#ifdef MS_WINDOWS -        if (len > INT_MAX) -            len = INT_MAX; -        n = send(s->sock_fd, buf, (int)len, flags); -#else -        n = send(s->sock_fd, buf, len, flags); -#endif -    } -    Py_END_ALLOW_THREADS -    if (timeout == 1) { +    ctx.buf = pbuf.buf; +    ctx.len = pbuf.len; +    ctx.flags = flags; +    if (sock_call(s, 1, sock_send_impl, &ctx) < 0) {          PyBuffer_Release(&pbuf); -        PyErr_SetString(socket_timeout, "timed out");          return NULL;      } -    END_SELECT_LOOP(s) -      PyBuffer_Release(&pbuf); -    if (n < 0) -        return s->errorhandler(); -    return PyLong_FromSsize_t(n); + +    return PyLong_FromSsize_t(ctx.result);  }  PyDoc_STRVAR(send_doc, @@ -3286,9 +3555,15 @@ static PyObject *  sock_sendall(PySocketSockObject *s, PyObject *args)  {      char *buf; -    Py_ssize_t len, n = -1; -    int flags = 0, timeout, saved_errno; +    Py_ssize_t len, n; +    int flags = 0;      Py_buffer pbuf; +    struct sock_send ctx; +    int has_timeout = (s->sock_timeout > 0); +    _PyTime_t interval = s->sock_timeout; +    _PyTime_t deadline = 0; +    int deadline_initialized = 0; +    PyObject *res = NULL;      if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags))          return NULL; @@ -3301,50 +3576,47 @@ sock_sendall(PySocketSockObject *s, PyObject *args)      }      do { -        Py_BEGIN_ALLOW_THREADS -        timeout = internal_select(s, 1); -        n = -1; -        if (!timeout) { -#ifdef MS_WINDOWS -            if (len > INT_MAX) -                len = INT_MAX; -            n = send(s->sock_fd, buf, (int)len, flags); -#else -            n = send(s->sock_fd, buf, len, flags); -#endif -        } -        Py_END_ALLOW_THREADS -        if (timeout == 1) { -            PyBuffer_Release(&pbuf); -            PyErr_SetString(socket_timeout, "timed out"); -            return NULL; +        if (has_timeout) { +            if (deadline_initialized) { +                /* recompute the timeout */ +                interval = deadline - _PyTime_GetMonotonicClock(); +            } +            else { +                deadline_initialized = 1; +                deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; +            } + +            if (interval <= 0) { +                PyErr_SetString(socket_timeout, "timed out"); +                goto done; +            }          } -        /* PyErr_CheckSignals() might change errno */ -        saved_errno = errno; + +        ctx.buf = buf; +        ctx.len = len; +        ctx.flags = flags; +        if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, interval) < 0) +            goto done; +        n = ctx.result; +        assert(n >= 0); + +        buf += n; +        len -= n; +          /* We must run our signal handlers before looping again.             send() can return a successful partial write when it is             interrupted, so we can't restrict ourselves to EINTR. */ -        if (PyErr_CheckSignals()) { -            PyBuffer_Release(&pbuf); -            return NULL; -        } -        if (n < 0) { -            /* If interrupted, try again */ -            if (saved_errno == EINTR) -                continue; -            else -                break; -        } -        buf += n; -        len -= n; +        if (PyErr_CheckSignals()) +            goto done;      } while (len > 0);      PyBuffer_Release(&pbuf); -    if (n < 0) -        return s->errorhandler(); -      Py_INCREF(Py_None); -    return Py_None; +    res = Py_None; + +done: +    PyBuffer_Release(&pbuf); +    return res;  }  PyDoc_STRVAR(sendall_doc, @@ -3356,6 +3628,32 @@ until all data is sent.  If an error occurs, it's impossible\n\  to tell how much data has been sent."); +struct sock_sendto { +    char *buf; +    Py_ssize_t len; +    int flags; +    int addrlen; +    sock_addr_t *addrbuf; +    Py_ssize_t result; +}; + +static int +sock_sendto_impl(PySocketSockObject *s, void *data) +{ +    struct sock_sendto *ctx = data; + +#ifdef MS_WINDOWS +    if (ctx->len > INT_MAX) +        ctx->len = INT_MAX; +    ctx->result = sendto(s->sock_fd, ctx->buf, (int)ctx->len, ctx->flags, +                         SAS2SA(ctx->addrbuf), ctx->addrlen); +#else +    ctx->result = sendto(s->sock_fd, ctx->buf, ctx->len, ctx->flags, +                         SAS2SA(ctx->addrbuf), ctx->addrlen); +#endif +    return (ctx->result >= 0); +} +  /* s.sendto(data, [flags,] sockaddr) method */  static PyObject * @@ -3363,11 +3661,10 @@ sock_sendto(PySocketSockObject *s, PyObject *args)  {      Py_buffer pbuf;      PyObject *addro; -    char *buf; -    Py_ssize_t len, arglen; +    Py_ssize_t arglen;      sock_addr_t addrbuf; -    int addrlen, flags, timeout; -    Py_ssize_t n = -1; +    int addrlen, flags; +    struct sock_sendto ctx;      flags = 0;      arglen = PyTuple_Size(args); @@ -3388,9 +3685,6 @@ sock_sendto(PySocketSockObject *s, PyObject *args)      if (PyErr_Occurred())          return NULL; -    buf = pbuf.buf; -    len = pbuf.len; -      if (!IS_SELECTABLE(s)) {          PyBuffer_Release(&pbuf);          return select_error(); @@ -3401,32 +3695,18 @@ sock_sendto(PySocketSockObject *s, PyObject *args)          return NULL;      } -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS -    timeout = internal_select_ex(s, 1, interval); -    if (!timeout) { -#ifdef MS_WINDOWS -        if (len > INT_MAX) -            len = INT_MAX; -        n = sendto(s->sock_fd, buf, (int)len, flags, -                   SAS2SA(&addrbuf), addrlen); -#else -        n = sendto(s->sock_fd, buf, len, flags, -                   SAS2SA(&addrbuf), addrlen); -#endif -    } -    Py_END_ALLOW_THREADS - -    if (timeout == 1) { +    ctx.buf = pbuf.buf; +    ctx.len = pbuf.len; +    ctx.flags = flags; +    ctx.addrlen = addrlen; +    ctx.addrbuf = &addrbuf; +    if (sock_call(s, 1, sock_sendto_impl, &ctx) < 0) {          PyBuffer_Release(&pbuf); -        PyErr_SetString(socket_timeout, "timed out");          return NULL;      } -    END_SELECT_LOOP(s)      PyBuffer_Release(&pbuf); -    if (n < 0) -        return s->errorhandler(); -    return PyLong_FromSsize_t(n); + +    return PyLong_FromSsize_t(ctx.result);  }  PyDoc_STRVAR(sendto_doc, @@ -3439,6 +3719,21 @@ For IP sockets, the address is a pair (hostaddr, port).");  /* The sendmsg() and recvmsg[_into]() methods require a working     CMSG_LEN().  See the comment near get_CMSG_LEN(). */  #ifdef CMSG_LEN +struct sock_sendmsg { +    struct msghdr *msg; +    int flags; +    ssize_t result; +}; + +static int +sock_sendmsg_impl(PySocketSockObject *s, void *data) +{ +    struct sock_sendmsg *ctx = data; + +    ctx->result = sendmsg(s->sock_fd, ctx->msg, ctx->flags); +    return (ctx->result >= 0); +} +  /* s.sendmsg(buffers[, ancdata[, flags[, address]]]) method */  static PyObject * @@ -3456,10 +3751,10 @@ sock_sendmsg(PySocketSockObject *s, PyObject *args)      } *cmsgs = NULL;      void *controlbuf = NULL;      size_t controllen, controllen_last; -    ssize_t bytes_sent = -1; -    int addrlen, timeout, flags = 0; +    int addrlen, flags = 0;      PyObject *data_arg, *cmsg_arg = NULL, *addr_arg = NULL, *data_fast = NULL,          *cmsg_fast = NULL, *retval = NULL; +    struct sock_sendmsg ctx;      if (!PyArg_ParseTuple(args, "O|OiO:sendmsg",                            &data_arg, &cmsg_arg, &flags, &addr_arg)) @@ -3613,23 +3908,12 @@ sock_sendmsg(PySocketSockObject *s, PyObject *args)          goto finally;      } -    BEGIN_SELECT_LOOP(s) -    Py_BEGIN_ALLOW_THREADS; -    timeout = internal_select_ex(s, 1, interval); -    if (!timeout) -        bytes_sent = sendmsg(s->sock_fd, &msg, flags); -    Py_END_ALLOW_THREADS; -    if (timeout == 1) { -        PyErr_SetString(socket_timeout, "timed out"); +    ctx.msg = &msg; +    ctx.flags = flags; +    if (sock_call(s, 1, sock_sendmsg_impl, &ctx) < 0)          goto finally; -    } -    END_SELECT_LOOP(s) -    if (bytes_sent < 0) { -        s->errorhandler(); -        goto finally; -    } -    retval = PyLong_FromSsize_t(bytes_sent); +    retval = PyLong_FromSsize_t(ctx.result);  finally:      PyMem_Free(controlbuf); @@ -3796,7 +4080,7 @@ static PyMethodDef sock_methods[] = {      {"share",         (PyCFunction)sock_share, METH_VARARGS,                        sock_share_doc},  #endif -    {"listen",            (PyCFunction)sock_listen, METH_O, +    {"listen",            (PyCFunction)sock_listen, METH_VARARGS,                        listen_doc},      {"recv",              (PyCFunction)sock_recv, METH_VARARGS,                        recv_doc}, @@ -3838,10 +4122,14 @@ static PyMemberDef sock_memberlist[] = {         {"family", T_INT, offsetof(PySocketSockObject, sock_family), READONLY, "the socket family"},         {"type", T_INT, offsetof(PySocketSockObject, sock_type), READONLY, "the socket type"},         {"proto", T_INT, offsetof(PySocketSockObject, sock_proto), READONLY, "the socket protocol"}, -       {"timeout", T_DOUBLE, offsetof(PySocketSockObject, sock_timeout), READONLY, "the socket timeout"},         {0},  }; +static PyGetSetDef sock_getsetlist[] = { +    {"timeout", (getter)sock_gettimeout, NULL, PyDoc_STR("the socket timeout")}, +    {NULL} /* sentinel */ +}; +  /* Deallocate a socket object in response to the last Py_DECREF().     First close the file description. */ @@ -3905,7 +4193,7 @@ sock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)      new = type->tp_alloc(type, 0);      if (new != NULL) {          ((PySocketSockObject *)new)->sock_fd = -1; -        ((PySocketSockObject *)new)->sock_timeout = -1.0; +        ((PySocketSockObject *)new)->sock_timeout = _PyTime_FromSeconds(-1);          ((PySocketSockObject *)new)->errorhandler = &set_error;      }      return new; @@ -4088,7 +4376,7 @@ static PyTypeObject sock_type = {      0,                                          /* tp_iternext */      sock_methods,                               /* tp_methods */      sock_memberlist,                            /* tp_members */ -    0,                                          /* tp_getset */ +    sock_getsetlist,                            /* tp_getset */      0,                                          /* tp_base */      0,                                          /* tp_dict */      0,                                          /* tp_descr_get */ @@ -4227,7 +4515,7 @@ Return the IP address (a string of the form '255.255.255.255') for a host.");  /* Convenience function common to gethostbyname_ex and gethostbyaddr */  static PyObject * -gethost_common(struct hostent *h, struct sockaddr *addr, int alen, int af) +gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af)  {      char **pch;      PyObject *rtn_tuple = (PyObject *)NULL; @@ -4944,21 +5232,22 @@ Convert an IP address from 32-bit packed binary format to string format");  static PyObject*  socket_inet_ntoa(PyObject *self, PyObject *args)  { -    char *packed_str; -    int addr_len; +    Py_buffer packed_ip;      struct in_addr packed_addr; -    if (!PyArg_ParseTuple(args, "y#:inet_ntoa", &packed_str, &addr_len)) { +    if (!PyArg_ParseTuple(args, "y*:inet_ntoa", &packed_ip)) {          return NULL;      } -    if (addr_len != sizeof(packed_addr)) { +    if (packed_ip.len != sizeof(packed_addr)) {          PyErr_SetString(PyExc_OSError,              "packed IP wrong length for inet_ntoa"); +        PyBuffer_Release(&packed_ip);          return NULL;      } -    memcpy(&packed_addr, packed_str, addr_len); +    memcpy(&packed_addr, packed_ip.buf, packed_ip.len); +    PyBuffer_Release(&packed_ip);      return PyUnicode_FromString(inet_ntoa(packed_addr));  } @@ -5069,8 +5358,7 @@ static PyObject *  socket_inet_ntop(PyObject *self, PyObject *args)  {      int af; -    char* packed; -    int len; +    Py_buffer packed_ip;      const char* retval;  #ifdef ENABLE_IPV6      char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1]; @@ -5081,31 +5369,35 @@ socket_inet_ntop(PyObject *self, PyObject *args)      /* Guarantee NUL-termination for PyUnicode_FromString() below */      memset((void *) &ip[0], '\0', sizeof(ip)); -    if (!PyArg_ParseTuple(args, "iy#:inet_ntop", &af, &packed, &len)) { +    if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {          return NULL;      }      if (af == AF_INET) { -        if (len != sizeof(struct in_addr)) { +        if (packed_ip.len != sizeof(struct in_addr)) {              PyErr_SetString(PyExc_ValueError,                  "invalid length of packed IP address string"); +            PyBuffer_Release(&packed_ip);              return NULL;          }  #ifdef ENABLE_IPV6      } else if (af == AF_INET6) { -        if (len != sizeof(struct in6_addr)) { +        if (packed_ip.len != sizeof(struct in6_addr)) {              PyErr_SetString(PyExc_ValueError,                  "invalid length of packed IP address string"); +            PyBuffer_Release(&packed_ip);              return NULL;          }  #endif      } else {          PyErr_Format(PyExc_ValueError,              "unknown address family %d", af); +        PyBuffer_Release(&packed_ip);          return NULL;      } -    retval = inet_ntop(af, packed, ip, sizeof(ip)); +    retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip)); +    PyBuffer_Release(&packed_ip);      if (!retval) {          PyErr_SetFromErrno(PyExc_OSError);          return NULL; @@ -5124,8 +5416,7 @@ static PyObject *  socket_inet_ntop(PyObject *self, PyObject *args)  {      int af; -    char* packed; -    int len; +    Py_buffer packed_ip;      struct sockaddr_in6 addr;      DWORD addrlen, ret, retlen;  #ifdef ENABLE_IPV6 @@ -5137,38 +5428,42 @@ socket_inet_ntop(PyObject *self, PyObject *args)      /* Guarantee NUL-termination for PyUnicode_FromString() below */      memset((void *) &ip[0], '\0', sizeof(ip)); -    if (!PyArg_ParseTuple(args, "iy#:inet_ntop", &af, &packed, &len)) { +    if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {          return NULL;      }      if (af == AF_INET) {          struct sockaddr_in * addr4 = (struct sockaddr_in *)&addr; -        if (len != sizeof(struct in_addr)) { +        if (packed_ip.len != sizeof(struct in_addr)) {              PyErr_SetString(PyExc_ValueError,                  "invalid length of packed IP address string"); +            PyBuffer_Release(&packed_ip);              return NULL;          }          memset(addr4, 0, sizeof(struct sockaddr_in));          addr4->sin_family = AF_INET; -        memcpy(&(addr4->sin_addr), packed, sizeof(addr4->sin_addr)); +        memcpy(&(addr4->sin_addr), packed_ip.buf, sizeof(addr4->sin_addr));          addrlen = sizeof(struct sockaddr_in);      } else if (af == AF_INET6) { -        if (len != sizeof(struct in6_addr)) { +        if (packed_ip.len != sizeof(struct in6_addr)) {              PyErr_SetString(PyExc_ValueError,                  "invalid length of packed IP address string"); +            PyBuffer_Release(&packed_ip);              return NULL;          }          memset(&addr, 0, sizeof(addr));          addr.sin6_family = AF_INET6; -        memcpy(&(addr.sin6_addr), packed, sizeof(addr.sin6_addr)); +        memcpy(&(addr.sin6_addr), packed_ip.buf, sizeof(addr.sin6_addr));          addrlen = sizeof(addr);      } else {          PyErr_Format(PyExc_ValueError,              "unknown address family %d", af); +        PyBuffer_Release(&packed_ip);          return NULL;      } +    PyBuffer_Release(&packed_ip);      retlen = sizeof(ip);      ret = WSAAddressToStringA((struct sockaddr*)&addr, addrlen, NULL, @@ -5405,12 +5700,14 @@ Get host and port for a sockaddr.");  static PyObject *  socket_getdefaulttimeout(PyObject *self)  { -    if (defaulttimeout < 0.0) { +    if (defaulttimeout < 0) {          Py_INCREF(Py_None);          return Py_None;      } -    else -        return PyFloat_FromDouble(defaulttimeout); +    else { +        double seconds = _PyTime_AsSecondsDouble(defaulttimeout); +        return PyFloat_FromDouble(seconds); +    }  }  PyDoc_STRVAR(getdefaulttimeout_doc, @@ -5423,19 +5720,10 @@ When the socket module is first imported, the default is None.");  static PyObject *  socket_setdefaulttimeout(PyObject *self, PyObject *arg)  { -    double timeout; +    _PyTime_t timeout; -    if (arg == Py_None) -        timeout = -1.0; -    else { -        timeout = PyFloat_AsDouble(arg); -        if (timeout < 0.0) { -            if (!PyErr_Occurred()) -                PyErr_SetString(PyExc_ValueError, -                                "Timeout value out of range"); -            return NULL; -        } -    } +    if (socket_parse_timeout(&timeout, arg) < 0) +        return NULL;      defaulttimeout = timeout; @@ -5782,11 +6070,15 @@ PyInit__socket(void)  #ifdef MS_WINDOWS      if (support_wsa_no_inherit == -1) { +#if defined(_MSC_VER) && _MSC_VER >= 1800 +        support_wsa_no_inherit = IsWindows7SP1OrGreater(); +#else          DWORD version = GetVersion();          DWORD major = (DWORD)LOBYTE(LOWORD(version));          DWORD minor = (DWORD)HIBYTE(LOWORD(version));          /* need Windows 7 SP1, 2008 R2 SP1 or later */ -        support_wsa_no_inherit = (major >= 6 && minor >= 1); +        support_wsa_no_inherit = major > 6 || (major == 6 && minor >= 1); +#endif      }  #endif @@ -6185,6 +6477,9 @@ PyInit__socket(void)  #ifdef  SO_PRIORITY      PyModule_AddIntMacro(m, SO_PRIORITY);  #endif +#ifdef  SO_MARK +    PyModule_AddIntMacro(m, SO_MARK); +#endif      /* Maximum number of connections for "listen" */  #ifdef  SOMAXCONN @@ -6322,6 +6617,9 @@ PyInit__socket(void)      PyModule_AddIntMacro(m, CAN_RAW_LOOPBACK);      PyModule_AddIntMacro(m, CAN_RAW_RECV_OWN_MSGS);  #endif +#ifdef HAVE_LINUX_CAN_RAW_FD_FRAMES +    PyModule_AddIntMacro(m, CAN_RAW_FD_FRAMES); +#endif  #ifdef HAVE_LINUX_CAN_BCM_H      PyModule_AddIntMacro(m, CAN_BCM);      PyModule_AddIntConstant(m, "CAN_BCM_TX_SETUP", TX_SETUP); | 
