diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index c18b33f09..23aa6dc11 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,19 @@
+2006-07-27  Corinna Vinschen  <corinna@vinschen.de>
+
+	* fhandler_socket.cc: Revert misguided attempt to handle FD_CLOSE error
+	conditions in evaluate_events.
+	(search_wsa_event_slot): Move wrongly placed memset in
+	fhandler_socket::init_events here.
+	(fhandler_socket::init_events): Initially set FD_WRITE event for
+	connectionless sockets.
+	* poll.cc (poll): Don't add sockets always to except_fds since select
+	is now supposed to do it right.
+	* select.cc (set_bits): Set connection state correctly for failed
+	af_local_connect on local sockets.  Remove socket special handling
+	for except_selected descriptors.
+	(peek_socket): Try to set the read/write/exception bits actually
+	correctly.
+
 2006-07-27  Brian Ford  <Brian.Ford@FlightSafety.com>
 
 	* fhandler_socket.cc (fhandler_socket::recvmsg): Remove unused tot
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 760dbc456..4a5177a02 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -386,7 +386,7 @@ struct wsa_event
 {
   LONG serial_number;
   long events;
-  int  errorcode;
+  int  connect_errorcode;
   pid_t owner;
 };
 
@@ -443,6 +443,7 @@ search_wsa_event_slot (LONG new_serial_number)
 	  return NULL;
 	}
     }
+  memset (&wsa_events[slot], 0, sizeof (wsa_event));
   wsa_events[slot].serial_number = new_serial_number;
   ReleaseMutex (wsa_slot_mtx);
   return wsa_events + slot;
@@ -490,7 +491,9 @@ fhandler_socket::init_events ()
       return false;
     }
   wsock_events = search_wsa_event_slot (new_serial_number);
-  memset (wsock_events, 0, sizeof *wsock_events);
+  /* sock type not yet set here. */
+  if (pc.dev == FH_UDP || pc.dev == FH_DGRAM)
+    wsock_events->events = FD_WRITE;
   return true;
 }
 
@@ -508,9 +511,7 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
 	  LOCK_EVENTS;
 	  wsock_events->events |= evts.lNetworkEvents;
 	  if (evts.lNetworkEvents & FD_CONNECT)
-	    wsock_events->errorcode = evts.iErrorCode[FD_CONNECT_BIT];
-	  else if (evts.lNetworkEvents & FD_CLOSE)
-	    wsock_events->errorcode = evts.iErrorCode[FD_CLOSE_BIT];
+	    wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT];
 	  UNLOCK_EVENTS;
 	  if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner)
 	    kill (wsock_events->owner, SIGURG);
@@ -520,22 +521,18 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
   LOCK_EVENTS;
   if ((events = (wsock_events->events & event_mask)) != 0)
     {
-      if (events & (FD_CONNECT | FD_CLOSE))
+      if (events & FD_CONNECT)
 	{
 	  int wsa_err = 0;
-	  if ((wsa_err = wsock_events->errorcode) != 0)
+	  if ((wsa_err = wsock_events->connect_errorcode) != 0)
 	    {
 	      WSASetLastError (wsa_err);
 	      ret = SOCKET_ERROR;
 	    }
-	  if (events & FD_CONNECT)
-	    {
-	      if (!wsock_events->errorcode)
-	        wsock_events->events |= FD_WRITE;
-	      wsock_events->events &= ~FD_CONNECT;
-	    }
-	  if (!(events & FD_CLOSE))
-	    wsock_events->errorcode = 0;
+	  else
+	    wsock_events->events |= FD_WRITE;
+	  wsock_events->events &= ~FD_CONNECT;
+	  wsock_events->connect_errorcode = 0;
 	}
       if (erase)
 	wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index 3ce46fab6..a7db49ef8 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -1,6 +1,6 @@
 /* poll.cc. Implements poll(2) via usage of select(2) call.
 
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
 
    This file is part of Cygwin.
 
@@ -63,9 +63,7 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
 	    FD_SET(fds[i].fd, read_fds);
 	  if (fds[i].events & POLLOUT)
 	    FD_SET(fds[i].fd, write_fds);
-	  /* On sockets, except_fds is needed to catch failed connects. */
-	  if ((fds[i].events & POLLPRI)
-	      || cygheap->fdtab[fds[i].fd]->is_socket ())
+	  if (fds[i].events & POLLPRI)
 	    FD_SET(fds[i].fd, except_fds);
 	}
       else if (fds[i].fd >= 0)
@@ -127,7 +125,6 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
 		  }
 		/* Handle failed connect. */
 		if (FD_ISSET(fds[i].fd, write_fds)
-		    && FD_ISSET(fds[i].fd, except_fds)
 		    && (sock = cygheap->fdtab[fds[i].fd]->is_socket ())
 		    && sock->connect_state () == connect_failed)
 		  fds[i].revents |= (POLLIN | POLLERR);
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index abfe9e5a3..e5b50d375 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -364,22 +364,20 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
 	{
 	  /* Special AF_LOCAL handling. */
 	  if (!me->read_ready && sock->connect_state () == connect_pending
-	      && sock->af_local_connect () && me->read_selected)
-	    UNIX_FD_SET (me->fd, readfds);
-	  sock->connect_state (connected);
+	      && sock->af_local_connect ())
+	    {
+	      if (me->read_selected)
+		UNIX_FD_SET (me->fd, readfds);
+	      sock->connect_state (connect_failed);
+	    }
+	  else
+	    sock->connect_state (connected);
 	}
       ready++;
     }
-  if ((me->except_selected || me->except_on_write) && me->except_ready)
+  if (me->except_selected && me->except_ready)
     {
-      if (me->except_on_write) /* Only on sockets */
-	{
-	  UNIX_FD_SET (me->fd, writefds);
-	  if ((sock = me->fh->is_socket ()))
-	    sock->connect_state (connect_failed);
-	}
-      if (me->except_selected)
-	UNIX_FD_SET (me->fd, exceptfds);
+      UNIX_FD_SET (me->fd, exceptfds);
       ready++;
     }
   select_printf ("ready %d", ready);
@@ -1264,23 +1262,21 @@ peek_socket (select_record *me, bool)
 {
   fhandler_socket *fh = (fhandler_socket *) me->fh;
   long events;
-  long evt_mask = (FD_CLOSE
-		   | (me->read_selected ? (FD_READ | FD_ACCEPT) : 0)
-		   | (me->write_selected ? (FD_WRITE | FD_CONNECT) : 0)
-		   | (me->except_selected ? (FD_OOB | FD_CONNECT) : 0));
+  /* Don't play with the settings again, unless having taken a deep look into
+     Richard W. Stevens Network Programming book.  Thank you. */
+  long evt_mask = (me->read_selected ? (FD_READ | FD_ACCEPT | FD_CLOSE) : 0)
+		| (me->write_selected ? (FD_WRITE | FD_CONNECT | FD_CLOSE) : 0)
+		| (me->except_selected ? FD_OOB : 0);
   int ret = fh->evaluate_events (evt_mask, events, false);
   if (me->read_selected)
-    me->read_ready |= !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE));
+    me->read_ready |= ret || !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE));
   if (me->write_selected)
-    {
-      if ((events & FD_CONNECT) && !ret)
-	me->write_ready = true;
-      else
-	me->write_ready |= !!(events & (FD_WRITE | FD_CLOSE));
-    }
+    me->write_ready |= ret || !!(events & (FD_WRITE | FD_CONNECT | FD_CLOSE));
   if (me->except_selected)
-    me->except_ready |= ret || !!(events & FD_OOB);
+    me->except_ready |= !!(events & FD_OOB);
 
+  select_printf ("read_ready: %d, write_ready: %d, except_ready: %d",
+		 me->read_ready, me->write_ready, me->except_ready);
   return me->read_ready || me->write_ready || me->except_ready;
 }