[Python-checkins] python/dist/src/Modules socketmodule.c,1.268,1.269

rhettinger@users.sourceforge.net rhettinger@users.sourceforge.net
Sat, 28 Jun 2003 20:08:07 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv31711

Modified Files:
	socketmodule.c 
Log Message:
SF patch #760257: add socket.timeout exception
(Contributed by Bob Halley)

Added a new exception, socket.timeout so that timeouts can be differentiated
from other socket exceptions.

Docs, more tests, and newsitem to follow.



Index: socketmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.c,v
retrieving revision 1.268
retrieving revision 1.269
diff -C2 -d -r1.268 -r1.269
*** socketmodule.c	10 May 2003 07:36:55 -0000	1.268
--- socketmodule.c	29 Jun 2003 03:08:05 -0000	1.269
***************
*** 329,332 ****
--- 329,333 ----
  static PyObject *socket_herror;
  static PyObject *socket_gaierror;
+ static PyObject *socket_timeout;
  
  #ifdef RISCOS
***************
*** 576,594 ****
  /* Do a select() on the socket, if necessary (sock_timeout > 0).
     The argument writing indicates the direction.
!    This does not raise an exception or return a success indicator;
!    we'll let the actual socket call do that. */
! static void
  internal_select(PySocketSockObject *s, int writing)
  {
  	fd_set fds;
  	struct timeval tv;
  
  	/* Nothing to do unless we're in timeout mode (not non-blocking) */
  	if (s->sock_timeout <= 0.0)
! 		return;
  
  	/* Guard against closed socket */
  	if (s->sock_fd < 0)
! 		return;
  
  	/* Construct the arguments to select */
--- 577,597 ----
  /* Do a select() on the socket, if necessary (sock_timeout > 0).
     The argument writing indicates the direction.
!    This does not raise an exception; we'll let our caller do that
!    after they've reacquired the interpreter lock.
!    Returns 1 on timeout, 0 otherwise. */
! static int
  internal_select(PySocketSockObject *s, int writing)
  {
  	fd_set fds;
  	struct timeval tv;
+ 	int n;
  
  	/* Nothing to do unless we're in timeout mode (not non-blocking) */
  	if (s->sock_timeout <= 0.0)
! 		return 0;
  
  	/* Guard against closed socket */
  	if (s->sock_fd < 0)
! 		return 0;
  
  	/* Construct the arguments to select */
***************
*** 600,606 ****
  	/* See if the socket is ready */
  	if (writing)
! 		select(s->sock_fd+1, NULL, &fds, NULL, &tv);
  	else
! 		select(s->sock_fd+1, &fds, NULL, NULL, &tv);
  }
  
--- 603,612 ----
  	/* See if the socket is ready */
  	if (writing)
! 		n = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
  	else
! 		n = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
! 	if (n == 0)
! 		return 1;
! 	return 0;
  }
  
***************
*** 1091,1094 ****
--- 1097,1101 ----
  	PyObject *addr = NULL;
  	PyObject *res = NULL;
+ 	int timeout;
  
  	if (!getsockaddrlen(s, &addrlen))
***************
*** 1096,1104 ****
  	memset(addrbuf, 0, addrlen);
  
  	Py_BEGIN_ALLOW_THREADS
! 	internal_select(s, 0);
! 	newfd = accept(s->sock_fd, (struct sockaddr *) addrbuf, &addrlen);
  	Py_END_ALLOW_THREADS
  
  #ifdef MS_WINDOWS
  	if (newfd == INVALID_SOCKET)
--- 1103,1124 ----
  	memset(addrbuf, 0, addrlen);
  
+ #ifdef MS_WINDOWS
+ 	newfd = INVALID_SOCKET;
+ #else
+ 	newfd = -1;
+ #endif
+ 
  	Py_BEGIN_ALLOW_THREADS
! 	timeout = internal_select(s, 0);
! 	if (!timeout)
! 		newfd = accept(s->sock_fd, (struct sockaddr *) addrbuf,
! 			       &addrlen);
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
+ 
  #ifdef MS_WINDOWS
  	if (newfd == INVALID_SOCKET)
***************
*** 1406,1413 ****
  
  static int
! internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen)
  {
! 	int res;
  
  	res = connect(s->sock_fd, addr, addrlen);
  
--- 1426,1435 ----
  
  static int
! internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
! 		 int *timeoutp)
  {
! 	int res, timeout;
  
+ 	timeout = 0;
  	res = connect(s->sock_fd, addr, addrlen);
  
***************
*** 1424,1430 ****
  			FD_SET(s->sock_fd, &fds);
  			res = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
! 			if (res == 0)
  				res = WSAEWOULDBLOCK;
! 			else if (res > 0)
  				res = 0;
  			/* else if (res < 0) an error occurred */
--- 1446,1453 ----
  			FD_SET(s->sock_fd, &fds);
  			res = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
! 			if (res == 0) {
  				res = WSAEWOULDBLOCK;
! 				timeout = 1;
! 			} else if (res > 0)
  				res = 0;
  			/* else if (res < 0) an error occurred */
***************
*** 1439,1443 ****
  	if (s->sock_timeout > 0.0) {
  		if (res < 0 && errno == EINPROGRESS) {
! 			internal_select(s, 1);
  			res = connect(s->sock_fd, addr, addrlen);
  			if (res < 0 && errno == EISCONN)
--- 1462,1466 ----
  	if (s->sock_timeout > 0.0) {
  		if (res < 0 && errno == EINPROGRESS) {
! 			timeout = internal_select(s, 1);
  			res = connect(s->sock_fd, addr, addrlen);
  			if (res < 0 && errno == EISCONN)
***************
*** 1450,1453 ****
--- 1473,1477 ----
  
  #endif
+ 	*timeoutp = timeout;
  
  	return res;
***************
*** 1462,1465 ****
--- 1486,1490 ----
  	int addrlen;
  	int res;
+ 	int timeout;
  
  	if (!getsockaddrarg(s, addro, &addr, &addrlen))
***************
*** 1467,1473 ****
  
  	Py_BEGIN_ALLOW_THREADS
! 	res = internal_connect(s, addr, addrlen);
  	Py_END_ALLOW_THREADS
  
  	if (res != 0)
  		return s->errorhandler();
--- 1492,1502 ----
  
  	Py_BEGIN_ALLOW_THREADS
! 	res = internal_connect(s, addr, addrlen, &timeout);
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
  	if (res != 0)
  		return s->errorhandler();
***************
*** 1491,1494 ****
--- 1520,1524 ----
  	int addrlen;
  	int res;
+ 	int timeout;
  
  	if (!getsockaddrarg(s, addro, &addr, &addrlen))
***************
*** 1496,1500 ****
  
  	Py_BEGIN_ALLOW_THREADS
! 	res = internal_connect(s, addr, addrlen);
  	Py_END_ALLOW_THREADS
  
--- 1526,1530 ----
  
  	Py_BEGIN_ALLOW_THREADS
! 	res = internal_connect(s, addr, addrlen, &timeout);
  	Py_END_ALLOW_THREADS
  
***************
*** 1717,1721 ****
  sock_recv(PySocketSockObject *s, PyObject *args)
  {
! 	int len, n, flags = 0;
  	PyObject *buf;
  #ifdef __VMS
--- 1747,1751 ----
  sock_recv(PySocketSockObject *s, PyObject *args)
  {
! 	int len, n = 0, flags = 0, timeout;
  	PyObject *buf;
  #ifdef __VMS
***************
*** 1739,1746 ****
  #ifndef __VMS
  	Py_BEGIN_ALLOW_THREADS
! 	internal_select(s, 0);
! 	n = recv(s->sock_fd, PyString_AS_STRING(buf), len, flags);
  	Py_END_ALLOW_THREADS
  
  	if (n < 0) {
  		Py_DECREF(buf);
--- 1769,1782 ----
  #ifndef __VMS
  	Py_BEGIN_ALLOW_THREADS
! 	timeout = internal_select(s, 0);
! 	if (!timeout)
! 		n = recv(s->sock_fd, PyString_AS_STRING(buf), len, flags);
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		Py_DECREF(buf);
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
  	if (n < 0) {
  		Py_DECREF(buf);
***************
*** 1764,1771 ****
  
  		Py_BEGIN_ALLOW_THREADS
!  	  	internal_select(s, 0);
! 		n = recv(s->sock_fd, read_buf, segment, flags);
  		Py_END_ALLOW_THREADS
  
  		if (n < 0) {
  			Py_DECREF(buf);
--- 1800,1813 ----
  
  		Py_BEGIN_ALLOW_THREADS
! 		timeout = internal_select(s, 0);
! 		if (!timeout)
! 			n = recv(s->sock_fd, read_buf, segment, flags);
  		Py_END_ALLOW_THREADS
  
+ 		if (timeout) {
+ 			Py_DECREF(buf);
+ 			PyErr_SetString(socket_timeout, "timed out");
+ 			return NULL;
+ 		}
  		if (n < 0) {
  			Py_DECREF(buf);
***************
*** 1806,1810 ****
  	PyObject *addr = NULL;
  	PyObject *ret = NULL;
! 	int len, n, flags = 0;
  	socklen_t addrlen;
  
--- 1848,1852 ----
  	PyObject *addr = NULL;
  	PyObject *ret = NULL;
! 	int len, n = 0, flags = 0, timeout;
  	socklen_t addrlen;
  
***************
*** 1820,1837 ****
  	Py_BEGIN_ALLOW_THREADS
  	memset(addrbuf, 0, addrlen);
! 	internal_select(s, 0);
! 	n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
  #ifndef MS_WINDOWS
  #if defined(PYOS_OS2) && !defined(PYCC_GCC)
! 		     (struct sockaddr *)addrbuf, &addrlen
  #else
! 		     (void *)addrbuf, &addrlen
  #endif
  #else
! 		     (struct sockaddr *)addrbuf, &addrlen
  #endif
! 		     );
  	Py_END_ALLOW_THREADS
  
  	if (n < 0) {
  		Py_DECREF(buf);
--- 1862,1885 ----
  	Py_BEGIN_ALLOW_THREADS
  	memset(addrbuf, 0, addrlen);
! 	timeout = internal_select(s, 0);
! 	if (!timeout)
! 		n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
  #ifndef MS_WINDOWS
  #if defined(PYOS_OS2) && !defined(PYCC_GCC)
! 			     (struct sockaddr *)addrbuf, &addrlen
  #else
! 			     (void *)addrbuf, &addrlen
  #endif
  #else
! 			     (struct sockaddr *)addrbuf, &addrlen
  #endif
! 			);
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		Py_DECREF(buf);
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
  	if (n < 0) {
  		Py_DECREF(buf);
***************
*** 1865,1869 ****
  {
  	char *buf;
! 	int len, n, flags = 0;
  #ifdef __VMS
  	int send_length;
--- 1913,1917 ----
  {
  	char *buf;
! 	int len, n = 0, flags = 0, timeout;
  #ifdef __VMS
  	int send_length;
***************
*** 1875,1882 ****
  #ifndef __VMS
  	Py_BEGIN_ALLOW_THREADS
! 	internal_select(s, 1);
! 	n = send(s->sock_fd, buf, len, flags);
  	Py_END_ALLOW_THREADS
  
  	if (n < 0)
  		return s->errorhandler();
--- 1923,1935 ----
  #ifndef __VMS
  	Py_BEGIN_ALLOW_THREADS
! 	timeout = internal_select(s, 1);
! 	if (!timeout)
! 		n = send(s->sock_fd, buf, len, flags);
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
  	if (n < 0)
  		return s->errorhandler();
***************
*** 1896,1902 ****
  		}
  		Py_BEGIN_ALLOW_THREADS
! 		internal_select(s, 1);
! 		n = send(s->sock_fd, buf, segment, flags);
  		Py_END_ALLOW_THREADS
  		if (n < 0) {
  			return s->errorhandler();
--- 1949,1960 ----
  		}
  		Py_BEGIN_ALLOW_THREADS
! 		timeout = internal_select(s, 1);
! 		if (!timeout)
! 			n = send(s->sock_fd, buf, segment, flags);
  		Py_END_ALLOW_THREADS
+ 		if (timeout) {
+ 			PyErr_SetString(socket_timeout, "timed out");
+ 			return NULL;
+ 		}
  		if (n < 0) {
  			return s->errorhandler();
***************
*** 1923,1927 ****
  {
  	char *buf;
! 	int len, n, flags = 0;
  
  	if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
--- 1981,1985 ----
  {
  	char *buf;
! 	int len, n = 0, flags = 0, timeout;
  
  	if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
***************
*** 1930,1934 ****
  	Py_BEGIN_ALLOW_THREADS
  	do {
! 		internal_select(s, 1);
  		n = send(s->sock_fd, buf, len, flags);
  		if (n < 0)
--- 1988,1994 ----
  	Py_BEGIN_ALLOW_THREADS
  	do {
! 		timeout = internal_select(s, 1);
! 		if (timeout)
! 			break;
  		n = send(s->sock_fd, buf, len, flags);
  		if (n < 0)
***************
*** 1939,1942 ****
--- 1999,2006 ----
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
  	if (n < 0)
  		return s->errorhandler();
***************
*** 1963,1967 ****
  	char *buf;
  	struct sockaddr *addr;
! 	int addrlen, len, n, flags;
  
  	flags = 0;
--- 2027,2031 ----
  	char *buf;
  	struct sockaddr *addr;
! 	int addrlen, len, n = 0, flags, timeout;
  
  	flags = 0;
***************
*** 1977,1984 ****
  
  	Py_BEGIN_ALLOW_THREADS
! 	internal_select(s, 1);
! 	n = sendto(s->sock_fd, buf, len, flags, addr, addrlen);
  	Py_END_ALLOW_THREADS
  
  	if (n < 0)
  		return s->errorhandler();
--- 2041,2053 ----
  
  	Py_BEGIN_ALLOW_THREADS
! 	timeout = internal_select(s, 1);
! 	if (!timeout)
! 		n = sendto(s->sock_fd, buf, len, flags, addr, addrlen);
  	Py_END_ALLOW_THREADS
  
+ 	if (timeout) {
+ 		PyErr_SetString(socket_timeout, "timed out");
+ 		return NULL;
+ 	}
  	if (n < 0)
  		return s->errorhandler();
***************
*** 3410,3413 ****
--- 3479,3488 ----
  	Py_INCREF(socket_gaierror);
  	PyModule_AddObject(m, "gaierror", socket_gaierror);
+ 	socket_timeout = PyErr_NewException("socket.timeout",
+ 					    socket_error, NULL);
+ 	if (socket_timeout == NULL)
+ 		return;
+ 	Py_INCREF(socket_timeout);
+ 	PyModule_AddObject(m, "timeout", socket_timeout);
  	Py_INCREF((PyObject *)&sock_type);
  	if (PyModule_AddObject(m, "SocketType",