Index: glib/giowin32.c
===================================================================
--- glib/giowin32.c	(revision 7373)
+++ glib/giowin32.c	(working copy)
@@ -111,8 +111,12 @@
   
   gboolean debug;
 
+  GSList *watches;		/* There can be several watches on a GIOChannel,
+				 * and we need to keep track of them
+				 */
+
   /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
-  HWND hwnd;			/* handle of window, or NULL */
+  HWND hwnd;			/* Handle of window, or NULL */
   
   /* Following fields are used by fd channels. */
   CRITICAL_SECTION mutex;
@@ -270,6 +274,7 @@
 g_io_channel_win32_init (GIOWin32Channel *channel)
 {
   channel->debug = g_io_win32_get_debug_flag ();
+  channel->watches = NULL;
   channel->buffer = NULL;
   channel->running = FALSE;
   channel->needs_close = FALSE;
@@ -697,6 +702,10 @@
   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
   int event_mask;
+  GSList *rover;
+#ifndef G_DISABLE_ASSERT
+  gboolean have_it;
+#endif
   
   *timeout = -1;
   
@@ -750,14 +759,33 @@
     case G_IO_WIN32_SOCKET:
       if (channel->debug)
 	g_print (" SOCK");
+
       event_mask = 0;
-      if (watch->condition & G_IO_IN)
-	event_mask |= (FD_READ | FD_ACCEPT);
-      if (watch->condition & G_IO_OUT)
-	event_mask |= (FD_WRITE | FD_CONNECT);
+      g_assert (channel->watches != NULL);
+      rover = channel->watches;
+      g_assert (!(have_it = FALSE));
+      while (rover)
+	{
+	  GIOWin32Watch *one_watch = rover->data;
+	  
+#ifndef G_DISABLE_ASSERT
+	  if (one_watch == watch)
+	    have_it = TRUE;
+#endif
+
+	  if (one_watch->source.flags & G_HOOK_FLAG_ACTIVE)
+	    {
+	      if (one_watch->condition & G_IO_IN)
+		event_mask |= (FD_READ | FD_ACCEPT);
+	      if (one_watch->condition & G_IO_OUT)
+		event_mask |= (FD_WRITE | FD_CONNECT);
+	    }
+	  rover = rover->next;
+	}
+      g_assert (have_it);
       event_mask |= FD_CLOSE;
 
-      if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
+      if (channel->event_mask != event_mask)
 	{
 	  if (channel->debug)
 	    g_print ("\n  WSAEventSelect(%d,%p,{%s})",
@@ -855,6 +883,7 @@
     case G_IO_WIN32_SOCKET:
       if (channel->debug)
 	g_print (" SOCK");
+#if 0
       if (channel->last_events & FD_WRITE)
 	{
 	  if (channel->debug)
@@ -862,6 +891,7 @@
 		     channel->fd, (HANDLE) watch->pollfd.fd);
 	}
       else
+#endif
 	{
 	  WSAEnumNetworkEvents (channel->fd, 0, &events);
 
@@ -889,7 +919,12 @@
 	    }
 	  else if (events.lNetworkEvents & FD_WRITE)
 	    channel->ever_writable = TRUE;
-	  channel->last_events = events.lNetworkEvents;
+	  /* Keep the FD_READ, FD_ACCEPT and FD_WRITE bits sticky in
+	   * channel->last_events.
+	   */
+	  channel->last_events =
+	    (channel->last_events & (FD_READ|FD_ACCEPT|FD_WRITE)) |
+	    events.lNetworkEvents;
 	}
 
       watch->pollfd.revents = 0;
@@ -994,12 +1029,10 @@
 
     case G_IO_WIN32_SOCKET:
       if (channel->debug)
-	g_print (" SOCK sock=%d", channel->fd);
-#if 0
-      CloseHandle ((HANDLE) watch->pollfd.fd);
-      channel->event = 0;
-      channel->event_mask = 0;
-#endif
+	g_print (" SOCK sock=%d nwatches=%d",
+		 channel->fd,
+		 channel->watches ? g_slist_length (channel->watches) : 0);
+      channel->watches = g_slist_remove (channel->watches, watch);
       break;
 
     default:
@@ -1104,6 +1137,7 @@
     WSAEventSelect (win32_channel->fd, NULL, 0);
   DeleteCriticalSection (&win32_channel->mutex);
 
+  g_slist_free (win32_channel->watches);
   g_free (win32_channel->buffer);
   g_free (win32_channel);
 }
@@ -1543,6 +1577,8 @@
   watch->channel = channel;
   g_io_channel_ref (channel);
   
+  win32_channel->watches = g_slist_prepend (win32_channel->watches, watch);
+
   watch->condition = condition;
 
   if (win32_channel->event == 0)
@@ -1552,9 +1588,10 @@
   watch->pollfd.events = condition;
   
   if (win32_channel->debug)
-    g_print ("g_io_win32_sock_create_watch: channel=%p sock=%d event=%p condition={%s}\n",
+    g_print ("g_io_win32_sock_create_watch: channel=%p sock=%d event=%p condition={%s} nwatches=%d\n",
 	     channel, win32_channel->fd, (HANDLE) watch->pollfd.fd,
-	     condition_to_string (watch->condition));
+	     condition_to_string (watch->condition),
+	     g_slist_length (win32_channel->watches));
 
   g_source_add_poll (source, &watch->pollfd);
 
