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