From: Victor Stinner Date: Fri, 22 Jul 2016 15:47:09 +0000 (+0200) Subject: Merge 3.5 (INVALID_SOCKET) X-Git-Tag: v3.6.0a4~139 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d3afb62b8fb38417c3f0bf6873ed64bd9efd8e43;p=python Merge 3.5 (INVALID_SOCKET) --- d3afb62b8fb38417c3f0bf6873ed64bd9efd8e43 diff --cc Modules/socketmodule.c index f8d39f6764,b34981cb6b..d21d18f7e3 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@@ -2576,22 -2563,17 +2576,22 @@@ static PyObject sock_close(PySocketSockObject *s) { SOCKET_T fd; + int res; - /* 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. - */ fd = s->sock_fd; - if (fd != -1) { - s->sock_fd = -1; + if (fd != INVALID_SOCKET) { + s->sock_fd = INVALID_SOCKET; + + /* 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. */ Py_BEGIN_ALLOW_THREADS - (void) SOCKETCLOSE(fd); + res = SOCKETCLOSE(fd); Py_END_ALLOW_THREADS + if (res < 0) { + return s->errorhandler(); + } } Py_INCREF(Py_None); return Py_None; @@@ -4194,45 -4164,22 +4194,45 @@@ static PyGetSetDef sock_getsetlist[] = First close the file description. */ static void -sock_dealloc(PySocketSockObject *s) +sock_finalize(PySocketSockObject *s) { + SOCKET_T fd; + PyObject *error_type, *error_value, *error_traceback; + + /* Save the current exception, if any. */ + PyErr_Fetch(&error_type, &error_value, &error_traceback); + - if (s->sock_fd != -1) { + if (s->sock_fd != INVALID_SOCKET) { - PyObject *exc, *val, *tb; - Py_ssize_t old_refcount = Py_REFCNT(s); - ++Py_REFCNT(s); - PyErr_Fetch(&exc, &val, &tb); - if (PyErr_WarnFormat(PyExc_ResourceWarning, 1, - "unclosed %R", s)) + if (PyErr_ResourceWarning((PyObject *)s, 1, "unclosed %R", s)) { /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) - PyErr_WriteUnraisable((PyObject *) s); - PyErr_Restore(exc, val, tb); - (void) SOCKETCLOSE(s->sock_fd); - Py_REFCNT(s) = old_refcount; + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable((PyObject *)s); + } + } + + /* Only close the socket *after* logging the ResourceWarning warning + to allow the logger to call socket methods like + socket.getsockname(). If the socket is closed before, socket + methods fails with the EBADF error. */ + fd = s->sock_fd; - s->sock_fd = -1; ++ s->sock_fd = INVALID_SOCKET; + + /* We do not want to retry upon EINTR: see sock_close() */ + Py_BEGIN_ALLOW_THREADS + (void) SOCKETCLOSE(fd); + Py_END_ALLOW_THREADS } + + /* Restore the saved exception. */ + PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +sock_dealloc(PySocketSockObject *s) +{ + if (PyObject_CallFinalizerFromDealloc((PyObject *)s) < 0) + return; + Py_TYPE(s)->tp_free((PyObject *)s); }