Kaydet (Commit) b9e916a0 authored tarafından Guido van Rossum's avatar Guido van Rossum

Correct several blunders in the timeout code, mostly my own fault (for

not testing it -- apparently test_timeout.py doesn't test anything
useful):

In internal_select():

- The tv_usec part of the timeout for select() was calculated wrong.

- The first argument to select() was one too low.

- The sense of the direction argument to internal_select() was
  inverted.

In PySocketSock_settimeout():

- The calls to internal_setblocking() were swapped.

Also, repaired some comments and fixed the test for the return value
of internal_select() in sendall -- this was in the original patch.
üst 8a13518d
...@@ -487,11 +487,12 @@ internal_setblocking(PySocketSockObject *s, int block) ...@@ -487,11 +487,12 @@ internal_setblocking(PySocketSockObject *s, int block)
} }
/* For access to the select module to poll the socket for timeout /* For access to the select module to poll the socket for timeout
* functionality. If reading is: 1 poll as read, 0, poll as write. * functionality. writing is 1 for writing, 0 for reading.
* Return value: -1 if error, 0 if not ready, >= 1 if ready. * Return value: -1 if error, 0 if not ready, >= 1 if ready.
* An exception is set when the return value is <= 0 (!).
*/ */
static int static int
internal_select(PySocketSockObject *s, int reading) internal_select(PySocketSockObject *s, int writing)
{ {
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
...@@ -499,15 +500,15 @@ internal_select(PySocketSockObject *s, int reading) ...@@ -499,15 +500,15 @@ internal_select(PySocketSockObject *s, int reading)
/* Construct the arguments to select */ /* Construct the arguments to select */
tv.tv_sec = (int)s->sock_timeout; tv.tv_sec = (int)s->sock_timeout;
tv.tv_usec = (int)(s->sock_timeout/1e6); tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(s->sock_fd, &fds); FD_SET(s->sock_fd, &fds);
/* See if the socket is ready */ /* See if the socket is ready */
if (reading) if (writing)
count = select(s->sock_fd, &fds, NULL, NULL, &tv); count = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
else else
count = select(s->sock_fd, NULL, &fds, NULL, &tv); count = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
/* Check for errors */ /* Check for errors */
if (count < 0) { if (count < 0) {
...@@ -1075,9 +1076,9 @@ static char setblocking_doc[] = ...@@ -1075,9 +1076,9 @@ static char setblocking_doc[] =
Set the socket to blocking (flag is true) or non-blocking (false).\n\ Set the socket to blocking (flag is true) or non-blocking (false).\n\
This uses the FIONBIO ioctl with the O_NDELAY flag."; This uses the FIONBIO ioctl with the O_NDELAY flag.";
/* s.settimeout (float | int | long) method. /* s.settimeout(float | None) method.
* Causes an exception to be raised when the integer number of seconds * Causes an exception to be raised when the given time has
* has elapsed when performing a blocking socket operation. * elapsed when performing a blocking socket operation.
*/ */
static PyObject * static PyObject *
PySocketSock_settimeout(PySocketSockObject *s, PyObject *arg) PySocketSock_settimeout(PySocketSockObject *s, PyObject *arg)
...@@ -1110,10 +1111,7 @@ PySocketSock_settimeout(PySocketSockObject *s, PyObject *arg) ...@@ -1110,10 +1111,7 @@ PySocketSock_settimeout(PySocketSockObject *s, PyObject *arg)
* non-blocking stuff. This makes sense because timeout stuff is * non-blocking stuff. This makes sense because timeout stuff is
* blocking by nature. * blocking by nature.
*/ */
if (value < 0.0) internal_setblocking(s, value < 0.0);
internal_setblocking(s, 0);
else
internal_setblocking(s, 1);
s->sock_blocking = 1; /* Always negate setblocking() */ s->sock_blocking = 1; /* Always negate setblocking() */
...@@ -1819,7 +1817,7 @@ PySocketSock_sendall(PySocketSockObject *s, PyObject *args) ...@@ -1819,7 +1817,7 @@ PySocketSock_sendall(PySocketSockObject *s, PyObject *args)
if (s->sock_timeout >= 0.0) { if (s->sock_timeout >= 0.0) {
if (s->sock_blocking) { if (s->sock_blocking) {
if (internal_select(s, 1) < 0) if (internal_select(s, 1) <= 0)
return NULL; return NULL;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment