summaryrefslogtreecommitdiff
path: root/Modules/socketmodule.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-04-03 13:22:27 +0200
committerVictor Stinner <victor.stinner@gmail.com>2015-04-03 13:22:27 +0200
commit45b87f06541e2aef57aba8471ee17a8896f6697e (patch)
tree7cb0246458369181e1fa35f37a1881d3cf816c69 /Modules/socketmodule.c
parente5a1ccdc5648669a45fd37781f99b022bdd1dd52 (diff)
downloadcpython-45b87f06541e2aef57aba8471ee17a8896f6697e.tar.gz
Issue #23834: Simplify timeout handling
* Use the new _PyTime_FromSeconds() function to set the timeout to -1 second for socket.settimeout(None). It avoids a special case in internal_select() because of a rounding issue: -1 nanosecond is rounded to 0 millisecond which means non-blocking, instead of blocking. * Check if the interval the negative in sock_call_ex() instead of doing the check in internal_select(). sock_call_ex() remembers if the socket has a timeout or not, which avoids a race condition if the timeout is modified in a different thread.
Diffstat (limited to 'Modules/socketmodule.c')
-rw-r--r--Modules/socketmodule.c40
1 files changed, 13 insertions, 27 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 89df463a52..5e267a4f29 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -629,17 +629,6 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval,
if (s->sock_fd < 0)
return 0;
- /* for connect(), we want to poll even if the socket is blocking */
- if (!connect) {
- /* Nothing to do unless we're in timeout mode (not non-blocking) */
- if (s->sock_timeout <= 0)
- return 0;
-
- /* Handling this condition here simplifies the select loops */
- if (interval < 0)
- return 1;
- }
-
/* Prefer poll, if available, since you can poll() any fd
* which can't be done with select(). */
#ifdef HAVE_POLL
@@ -654,22 +643,14 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval,
}
/* s->sock_timeout is in seconds, timeout in ms */
- if (interval >= 0)
- ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
- else
- ms = -1;
+ ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
assert(ms <= INT_MAX);
Py_BEGIN_ALLOW_THREADS;
n = poll(&pollfd, 1, (int)ms);
Py_END_ALLOW_THREADS;
#else
- if (interval >= 0)
- _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING);
- else {
- tv.tv_sec = -1;
- tv.tv_sec = 0;
- }
+ _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING);
FD_ZERO(&fds);
FD_SET(s->sock_fd, &fds);
@@ -741,9 +722,9 @@ sock_call_ex(PySocketSockObject *s,
/* For connect(), poll even for blocking socket. The connection
runs asynchronously. */
if (has_timeout || connect) {
- _PyTime_t interval;
-
if (has_timeout) {
+ _PyTime_t interval;
+
if (deadline_initialized) {
/* recompute the timeout */
interval = deadline - _PyTime_GetMonotonicClock();
@@ -753,11 +734,16 @@ sock_call_ex(PySocketSockObject *s,
deadline = _PyTime_GetMonotonicClock() + s->sock_timeout;
interval = s->sock_timeout;
}
+
+ if (interval >= 0)
+ res = internal_select(s, writing, interval, connect);
+ else
+ res = 1;
+ }
+ else {
+ res = internal_select(s, writing, -1, connect);
}
- else
- interval = -1;
- res = internal_select(s, writing, interval, connect);
if (res == -1) {
if (err)
*err = GET_SOCK_ERROR;
@@ -2332,7 +2318,7 @@ socket_parse_timeout(_PyTime_t *timeout, PyObject *timeout_obj)
int overflow = 0;
if (timeout_obj == Py_None) {
- *timeout = -1;
+ *timeout = _PyTime_FromSeconds(-1);
return 0;
}