summaryrefslogtreecommitdiff
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-03-31 16:08:22 +0200
committerVictor Stinner <victor.stinner@gmail.com>2015-03-31 16:08:22 +0200
commitdfd099ab5fa516d18d6edb34cff10eb1ae09dde5 (patch)
tree9962dc8254117b2660f191580fe1c6f9e05df339 /Modules
parentb069be5549e7ba18837a6a03b74002a3162f064a (diff)
downloadcpython-dfd099ab5fa516d18d6edb34cff10eb1ae09dde5.tar.gz
Issue #23618: Refactor internal_connect()
The function now returns the error code instead of using the global errno (POSIX) or WSAGetLastError() (Windows). internal_connect() now returns errno if getsockopt() fails.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/socketmodule.c92
1 files changed, 57 insertions, 35 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index a33c12740c..b58e134121 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2450,7 +2450,7 @@ static int
internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
int *timeoutp)
{
- int res, timeout;
+ int err, res, timeout;
timeout = 0;
@@ -2460,9 +2460,12 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
#ifdef MS_WINDOWS
- if (s->sock_timeout > 0
- && res < 0 && WSAGetLastError() == WSAEWOULDBLOCK
- && IS_SELECTABLE(s)) {
+ if (res < 0)
+ err = WSAGetLastError();
+ else
+ err = res;
+
+ if (s->sock_timeout > 0 && err == WSAEWOULDBLOCK && IS_SELECTABLE(s)) {
/* This is a mess. Best solution: trust select */
fd_set fds;
fd_set fds_exc;
@@ -2481,38 +2484,46 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
Py_END_ALLOW_THREADS
if (res == 0) {
- res = WSAEWOULDBLOCK;
+ err = WSAEWOULDBLOCK;
timeout = 1;
- } else if (res > 0) {
- if (FD_ISSET(s->sock_fd, &fds))
+ }
+ else if (res > 0) {
+ if (FD_ISSET(s->sock_fd, &fds)) {
/* The socket is in the writable set - this
means connected */
- res = 0;
+ err = 0;
+ }
else {
/* As per MS docs, we need to call getsockopt()
to get the underlying error */
- int res_size = sizeof res;
+ int res_size;
+
/* 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();
+
+ res_size = sizeof res;
+ if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
+ (char *)&res, &res_size)) {
+ err = res;
+ }
+ else {
+ err = WSAGetLastError();
+ }
}
}
- /* else if (res < 0) an error occurred */
+ else {
+ /* select() failed */
+ err = WSAGetLastError();
+ }
}
- if (res < 0)
- res = WSAGetLastError();
-
#else
+ if (res < 0)
+ err = errno;
+ else
+ err = 0;
- if (s->sock_timeout > 0
- && res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) {
+ if (s->sock_timeout > 0 && err == EINPROGRESS && IS_SELECTABLE(s)) {
timeout = internal_connect_select(s);
@@ -2521,27 +2532,31 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
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;
+ if (!getsockopt(s->sock_fd, SOL_SOCKET,
+ SO_ERROR, &res, &res_size)) {
+ if (res == EISCONN)
+ res = 0;
+ err = res;
+ }
+ else {
+ /* getsockopt() failed */
+ err = errno;
+ }
}
else if (timeout == -1) {
- res = errno; /* had error */
+ /* select failed */
+ err = errno;
+ }
+ else {
+ err = EWOULDBLOCK; /* timed out */
}
- else
- res = EWOULDBLOCK; /* timed out */
}
- if (res < 0)
- res = errno;
-
#endif
*timeoutp = timeout;
- assert(res >= 0);
- return res;
+ assert(err >= 0);
+ return err;
}
/* s.connect(sockaddr) method */
@@ -2566,6 +2581,13 @@ sock_connect(PySocketSockObject *s, PyObject *addro)
if (res < 0)
return NULL;
if (res != 0) {
+#ifdef MS_WINDOWS
+ /* getsockopt also clears WSAGetLastError,
+ so reset it back. */
+ WSASetLastError(res);
+#else
+ errno = res;
+#endif
return s->errorhandler();
}
Py_INCREF(Py_None);