Commit 11ba0949 authored by Guido van Rossum's avatar Guido van Rossum

Major overhaul of timeout sockets:

- setblocking(0) and settimeout(0) are now equivalent, and ditto for
  setblocking(1) and settimeout(None).

- Don't raise an exception from internal_select(); let the final call
  report the error (this means you will get an EAGAIN error instead of
  an ETIMEDOUT error -- I don't care).

- Move the select to inside the Py_{BEGIN,END}_ALLOW_THREADS brackets,
  so other theads can run (this was a bug in the original code).

- Redid the retry logic in connect() and connect_ex() to avoid masking
  errors.  This probably doesn't work for Windows yet; I'll fix that
  next.  It may also fail on other platforms, depending on what
  retrying a connect does; I need help with this.

- Get rid of the retry logic in accept().  I don't think it was needed
  at all.  But I may be wrong.
parent dfad1a90
......@@ -72,8 +72,9 @@ argument types and out-of-memory conditions can be raised; errors
related to socket or address semantics raise the error
\exception{socket.error}.
Non-blocking mode is supported through the
\method{setblocking()} method.
Non-blocking mode is supported through
\method{setblocking()}. A generalization of this based on timeouts
is supported through \method{settimeout()}.
The module \module{socket} exports the following constants and functions:
......@@ -284,8 +285,7 @@ checked --- subsequent operations on the object may fail if the file
descriptor is invalid. This function is rarely needed, but can be
used to get or set socket options on a socket passed to a program as
standard input or output (such as a server started by the \UNIX{} inet
daemon). The socket is assumed to be in blocking mode without
a timeout.
daemon). The socket is assumed to be in blocking mode.
Availability: \UNIX.
\end{funcdesc}
......@@ -514,38 +514,39 @@ all sockets are in blocking mode. In non-blocking mode, if a
\method{send()} call can't immediately dispose of the data, a
\exception{error} exception is raised; in blocking mode, the calls
block until they can proceed.
\code{s.setblocking(0)} is equivalent to \code{s.settimeout(0)};
\code{s.setblocking(1)} is equivalent to \code{s.settimeout(None)}.
\end{methoddesc}
\begin{methoddesc}[socket]{settimeout}{value}
Set a timeout on blocking socket operations. Value can be a
nonnegative float expressing seconds, or \code{None}. If a float is
Set a timeout on blocking socket operations. The \var{value} argument
can be a nonnegative float expressing seconds, or \code{None}.
If a float is
given, subsequent socket operations will raise an \exception{error}
exception if the timeout period \var{value} has elapsed before the
operation has completed. Setting a timeout of \code{None} disables
timeouts on socket operations.
\code{s.settimeout(0.0)} is equivalent to \code{s.blocking(0)};
\code{s.settimeout(None)} is equivalent to \code{s.setblocking(1)}.
\versionadded{2.3}
\end{methoddesc}
\begin{methoddesc}[socket]{gettimeout}{}
Returns the timeout in floating seconds associated with socket
operations, or \code{None} if no timeout is set.
operations, or \code{None} if no timeout is set. This reflects
the last call to \method{setblocking()} or \method{settimeout()}.
\versionadded{2.3}
\end{methoddesc}
Some notes on the interaction between socket blocking and timeouts: A
socket object can be in one of three modes: blocking, non-blocking, or
timout. Sockets are always created in blocking mode. In blocking
mode, operations block until complete. In non-blocking mode,
operations fail (with an error that is unfortunately system-dependent)
if they cannot be completed immediately. In timeout mode, operations
fail if they cannot be completed within the timeout specified for the
socket.
Calling \method{settimeout()} cancels non-blocking mode as set by
\method{setblocking()}; calling \method{setblocking()} cancels a
previously set timeout. Setting the timeout to zero acts similarly
but is implemented different than setting the socket in non-blocking
mode (this could be considered a bug and may even be fixed).
Some notes on socket blocking and timeouts: A socket object can be in
one of three modes: blocking, non-blocking, or timout. Sockets are
always created in blocking mode. In blocking mode, operations block
until complete. In non-blocking mode, operations fail (with an error
that is unfortunately system-dependent) if they cannot be completed
immediately. In timeout mode, operations fail if they cannot be
completed within the timeout specified for the socket. The
\method{setblocking()} method is simply a shorthand for certain
\method{settimeout()} calls.
Timeout mode internally sets the socket in non-blocking mode. The
blocking and timeout modes are shared between file descriptors and
......
......@@ -51,7 +51,10 @@ class ThreadableTest:
self.queue = Queue.Queue(1)
# Do some munging to start the client test.
test_method = getattr(self, '_' + self._TestCase__testMethodName)
methodname = self.id()
i = methodname.rfind('.')
methodname = methodname[i+1:]
test_method = getattr(self, '_' + methodname)
self.client_thread = thread.start_new_thread(
self.clientRun, (test_method,))
......
......@@ -59,17 +59,17 @@ class CreationTestCase(unittest.TestCase):
self.assertRaises(ValueError, self.sock.settimeout, -1L)
self.assertRaises(ValueError, self.sock.settimeout, -1.0)
def testTimeoutThenoBlocking(self):
def testTimeoutThenBlocking(self):
"Test settimeout() followed by setblocking()"
self.sock.settimeout(10)
self.sock.setblocking(1)
self.assertEqual(self.sock.gettimeout(), None)
self.sock.setblocking(0)
self.assertEqual(self.sock.gettimeout(), None)
self.assertEqual(self.sock.gettimeout(), 0.0)
self.sock.settimeout(10)
self.sock.setblocking(0)
self.assertEqual(self.sock.gettimeout(), None)
self.assertEqual(self.sock.gettimeout(), 0.0)
self.sock.setblocking(1)
self.assertEqual(self.sock.gettimeout(), None)
......
This diff is collapsed.
......@@ -83,9 +83,8 @@ typedef struct {
PyObject *(*errorhandler)(void); /* Error handler; checks
errno, returns NULL and
sets a Python exception */
int sock_blocking; /* Flag indicated whether the
socket is in blocking mode */
double sock_timeout; /* Operation timeout value */
double sock_timeout; /* Operation timeout in seconds;
0.0 means non-blocking */
} PySocketSockObject;
/* --- C API ----------------------------------------------------*/
......
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