possible error in socketmodule / asyncore on win32

Garth news at garthy.com
Thu Jul 24 22:18:53 CEST 2003


Hi,

I think there's an error in ther socketmodule.c code
under windows. The code in internal connect should test
  exceptfds to check for connecttion refused. If this is so it
should call getsockopt(SOL_SOCKET, SO_ERROR,..) to get the error
status. (Source microsoft Platform SDK)

If this isn't then the asynccore module fails on windows and never
returns connection refused.

The code should probably look something like this (untested)

if (s->sock_timeout > 0.0) {
     if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK) {
	/* This is a mess.  Best solution: trust select */
	fd_set exfds;
	struct timeval tv;
	tv.tv_sec = (int)s->sock_timeout;
	tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
	FD_ZERO(&exfds);
	FD_SET(s->sock_fd, &exfds);
	/* Platform SDK says so */
	res = select(s->sock_fd+1, NULL, NULL, &exfds, &tv);
	if (res == 0)
	{
	    if( FD_ISSET( &exfds ) )
	    {
		/* Get the real reason */
			getsockopt(s->sock_fd,SOL_SOCKET,SO_ERROR,(char*)&res,sizeof(res));
	    }
	    else
	    {
		res = 0;
	    }
	}
	else if (res > 0)
	{
	    res = WSAGetLastError();
	}
     }
} else if (res < 0)
     res = WSAGetLastError();

This still doesn't solve the problem in asyncore as it doesn't test 
exfss. I guess it should test exfs if it's not connected (again not tested)

def poll(timeout=0.0, map=None):
     if map is None:
         map = socket_map
     if map:
         r = []; w = []; e = []
         for fd, obj in map.items():
             if obj.readable():
                 r.append(fd)
             if obj.writable():
                 w.append(fd)

             if sys.platform == 'win32':
                 if not obj.connected:
                     e.append(fd)
         if [] == r == w == e:
             time.sleep(timeout)
         else:
             try:
                 r, w, e = select.select(r, w, e, timeout)
             except select.error, err:
                 if err[0] != EINTR:
                     raise
                 else:
                     return

         if sys.platform == 'win32':
             for fd in e:
                 obj = map.get(fd)
                 if obj is None:
                     continue
                 errno = fs.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
                 raise socket.error,(errno,socketerrorTab[error])

         for fd in r:
             obj = map.get(fd)
             if obj is None:
                 continue
             read(obj)

         for fd in w:
             obj = map.get(fd)
             if obj is None:
                 continue
             write(obj)

Not really sure where to report this so I'm posting here.

This is all against 2.3c1

(Cheers to all for a wicked language.)

Garth







More information about the Python-list mailing list