Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b9e916a

Browse files
committed
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.
1 parent 8a13518 commit b9e916a

1 file changed

Lines changed: 12 additions & 14 deletions

File tree

Modules/socketmodule.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -487,27 +487,28 @@ internal_setblocking(PySocketSockObject *s, int block)
487487
}
488488

489489
/* For access to the select module to poll the socket for timeout
490-
* functionality. If reading is: 1 poll as read, 0, poll as write.
490+
* functionality. writing is 1 for writing, 0 for reading.
491491
* Return value: -1 if error, 0 if not ready, >= 1 if ready.
492+
* An exception is set when the return value is <= 0 (!).
492493
*/
493494
static int
494-
internal_select(PySocketSockObject *s, int reading)
495+
internal_select(PySocketSockObject *s, int writing)
495496
{
496497
fd_set fds;
497498
struct timeval tv;
498499
int count;
499500

500501
/* Construct the arguments to select */
501502
tv.tv_sec = (int)s->sock_timeout;
502-
tv.tv_usec = (int)(s->sock_timeout/1e6);
503+
tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
503504
FD_ZERO(&fds);
504505
FD_SET(s->sock_fd, &fds);
505506

506507
/* See if the socket is ready */
507-
if (reading)
508-
count = select(s->sock_fd, &fds, NULL, NULL, &tv);
508+
if (writing)
509+
count = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
509510
else
510-
count = select(s->sock_fd, NULL, &fds, NULL, &tv);
511+
count = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
511512

512513
/* Check for errors */
513514
if (count < 0) {
@@ -1075,9 +1076,9 @@ static char setblocking_doc[] =
10751076
Set the socket to blocking (flag is true) or non-blocking (false).\n\
10761077
This uses the FIONBIO ioctl with the O_NDELAY flag.";
10771078

1078-
/* s.settimeout (float | int | long) method.
1079-
* Causes an exception to be raised when the integer number of seconds
1080-
* has elapsed when performing a blocking socket operation.
1079+
/* s.settimeout(float | None) method.
1080+
* Causes an exception to be raised when the given time has
1081+
* elapsed when performing a blocking socket operation.
10811082
*/
10821083
static PyObject *
10831084
PySocketSock_settimeout(PySocketSockObject *s, PyObject *arg)
@@ -1110,10 +1111,7 @@ PySocketSock_settimeout(PySocketSockObject *s, PyObject *arg)
11101111
* non-blocking stuff. This makes sense because timeout stuff is
11111112
* blocking by nature.
11121113
*/
1113-
if (value < 0.0)
1114-
internal_setblocking(s, 0);
1115-
else
1116-
internal_setblocking(s, 1);
1114+
internal_setblocking(s, value < 0.0);
11171115

11181116
s->sock_blocking = 1; /* Always negate setblocking() */
11191117

@@ -1819,7 +1817,7 @@ PySocketSock_sendall(PySocketSockObject *s, PyObject *args)
18191817

18201818
if (s->sock_timeout >= 0.0) {
18211819
if (s->sock_blocking) {
1822-
if (internal_select(s, 1) < 0)
1820+
if (internal_select(s, 1) <= 0)
18231821
return NULL;
18241822
}
18251823
}

0 commit comments

Comments
 (0)