[svn] w32pth - r18 - trunk

svn author marcus cvs at cvs.gnupg.org
Tue Feb 12 13:50:11 CET 2008


Author: marcus
Date: 2008-02-12 13:50:10 +0100 (Tue, 12 Feb 2008)
New Revision: 18

Removed:
   trunk/Makefile.in
Modified:
   trunk/ChangeLog
   trunk/w32-pth.c
Log:
2008-02-12  Marcus Brinkmann  <marcus at g10code.de>

	* Makefile.in: Removed.
	* w32-pth.c (NO_PTH_MODE_STATIC): New macro.  Use it everywhere
	where we have to release event resources.
	(spawn_helper_thread, wait_fd_thread, wait_for_fd): Removed.
	(do_pth_wait): Use WSAEventSelect for sockets.


[The diff below has been truncated]

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2008-02-12 01:44:33 UTC (rev 17)
+++ trunk/ChangeLog	2008-02-12 12:50:10 UTC (rev 18)
@@ -1,5 +1,11 @@
 2008-02-12  Marcus Brinkmann  <marcus at g10code.de>
 
+	* Makefile.in: Removed.
+	* w32-pth.c (NO_PTH_MODE_STATIC): New macro.  Use it everywhere
+	where we have to release event resources.
+	(spawn_helper_thread, wait_fd_thread, wait_for_fd): Removed.
+	(do_pth_wait): Use WSAEventSelect for sockets.
+
 	* Makefile.am (libw32pth_la_SOURCES): Add debug.h, w32-io.h and
 	w32-io.c.
 	* libw32pth.def: Add pth_pipe, pth_close.

Deleted: trunk/Makefile.in

Modified: trunk/w32-pth.c
===================================================================
--- trunk/w32-pth.c	2008-02-12 01:44:33 UTC (rev 17)
+++ trunk/w32-pth.c	2008-02-12 12:50:10 UTC (rev 18)
@@ -57,6 +57,9 @@
 #error long long is not 64 bit
 #endif
 
+/* FIXME: We can only undefine this when we have static thread-local
+   event allocation.  */
+#define NO_PTH_MODE_STATIC 1
 
 /* States whether this module has been initialized.  */
 static int pth_initialized;
@@ -497,14 +500,19 @@
   if (ev_extra)
     {
       pth_event_isolate (ev);
-
       if (ev->status != PTH_STATUS_OCCURRED)
 	{
+#ifdef NO_PTH_MODE_STATIC
+	  do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
 	  errno = EINTR;
 	  leave_pth (__FUNCTION__);
 	  return -1;
 	}
     }
+#ifdef NO_PTH_MODE_STATIC
+  do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
 
   n = do_pth_read (fd, buffer, size);
 
@@ -594,11 +602,17 @@
 
       if (pth_event_status(ev) != PTH_STATUS_OCCURRED)
 	{
+#ifdef NO_PTH_MODE_STATIC
+  do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
 	  errno = EINTR;
 	  leave_pth (__FUNCTION__);
 	  return -1;
 	}
     }
+#ifdef NO_PTH_MODE_STATIC
+  do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
 
   n = do_pth_write (fd, buffer, size);
 
@@ -818,12 +832,19 @@
           pth_event_isolate (ev);
           if (ev && ev->status != PTH_STATUS_OCCURRED)
             {
+#ifdef NO_PTH_MODE_STATIC
+	      do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
               pth_fdmode (fd, fdmode);
               leave_pth (__FUNCTION__);
               return -1;
             }
         }
     }
+#ifdef NO_PTH_MODE_STATIC
+  if (ev)
+    do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
 
   pth_fdmode (fd, fdmode);
   leave_pth (__FUNCTION__);
@@ -1189,8 +1210,11 @@
 
       /* else wait a little bit */
       ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
-                     pth_timeout (0,250000));
+		     pth_timeout (0,250000));
       pth_wait(ev);
+#ifdef NO_PTH_MODE_STATIC
+      do_pth_event_free (ev, PTH_FREE_THIS);
+#endif
     }
 
   pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name);
@@ -1293,7 +1317,7 @@
 
   /* We don't support static yet but we need to consume the
      argument.  */
-  if ( (spec & PTH_MODE_STATIC) )
+  if ((spec & PTH_MODE_STATIC))
     {
       ev->flags |= PTH_MODE_STATIC;
       va_arg (arg, pth_key_t *);
@@ -1433,43 +1457,6 @@
 }
 
 
-static int
-wait_for_fd (int fd, int is_read, int nwait)
-{
-  struct timeval tv;
-  fd_set r;
-  fd_set w;
-  int n;
-
-  FD_ZERO (&r);
-  FD_ZERO (&w);    
-  FD_SET (fd, is_read ? &r : &w);
-
-  tv.tv_sec = nwait;
-  tv.tv_usec = 0;
-
-  while (1)
-    {
-      n = select (fd+1, &r, &w, NULL, &tv);
-      if (DBG_INFO)
-        fprintf (dbgfp, "%s: wait_for_fd=%d fd %d (ec=%d)\n",
-                 log_get_prefix (NULL), n, fd,(int)WSAGetLastError ());
-      if (n == -1)
-        break;
-      if (!n)
-        continue;
-      if (n == 1)
-        {
-          if (is_read && FD_ISSET (fd, &r))
-            break;
-          else if (FD_ISSET (fd, &w))
-            break;
-        }
-    }
-  return 0;
-}
-
-
 static void *
 launch_thread (void *arg)
 {
@@ -1641,62 +1628,16 @@
 
 
 
-static pth_t
-spawn_helper_thread (void *(*func)(void *), void *arg)
-{
-  SECURITY_ATTRIBUTES sa;
-  DWORD tid;
-  HANDLE th;
-
-  memset (&sa, 0, sizeof sa);
-  sa.bInheritHandle = TRUE;
-  sa.lpSecurityDescriptor = NULL;
-  sa.nLength = sizeof sa;
-
-  /* FIXME: We should poll the socket non-blockingly first, as
-     otherwise we might be starved by a concurrent timer event.  Also,
-     this helps us to update the event status (set/reset it here)
-     properly.  See note in do_pth_wait below.  */
-  if (DBG_INFO)
-    fprintf (dbgfp, "%s: spawn_helper_thread creating thread ...\n",
-             log_get_prefix (NULL));
-  th = CreateThread (&sa, 32*1024,
-                     (LPTHREAD_START_ROUTINE)func,
-                     arg, 0, &tid);
-  if (DBG_INFO)
-    fprintf (dbgfp, "%s: spawn_helper_thread created thread %p\n",
-             log_get_prefix (NULL), th);
-
-  return th;
-}
-
-
-
-static void *
-wait_fd_thread (void * ctx)
-{
-  pth_event_t ev = ctx;
-
-  wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600);
-  if (DBG_INFO)
-    fprintf (dbgfp, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL));
-  set_event (ev->hd);
-  ExitThread (0);
-  return NULL;
-}
-
-
-
 static int
 do_pth_wait (pth_event_t ev)
 {
   char strerr[256];
   HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2];
   pth_event_t evarray[MAXIMUM_WAIT_OBJECTS/2];
-  HANDLE threadlist[MAXIMUM_WAIT_OBJECTS/2];
   DWORD n;
   int pos, idx, thlstidx, i;
   pth_event_t r;
+  int count;
 
   if (!ev)
     return 0;
@@ -1736,17 +1677,35 @@
           
         case PTH_EVENT_FD:
 	  {
+	    int res;
 	    int fd = r->u.fd;
 	    int is_socket = fd_is_socket (fd);
 
 	    if (is_socket)
 	      {
-		if (DBG_INFO)
-		  fprintf (dbgfp, "pth_wait: spawn wait_fd_thread\n");
+		WSAEVENT sockevent = WSACreateEvent ();
+		long flags;
 
-		evarray[pos] = r;  
-		waitbuf[pos++] = r->hd;
-		threadlist[thlstidx++] = spawn_helper_thread (wait_fd_thread, r);
+		/* Note: This restricts us to one event in one active
+		   wait per socket.  But that's commonly the case
+		   anyway.  */
+		if (r->flags & PTH_UNTIL_FD_READABLE)
+		  flags = FD_READ | FD_ACCEPT;
+		else
+		  flags = FD_WRITE;
+
+		res = WSAEventSelect (fd, sockevent, flags);
+		if (res)
+		  {
+		    if (DBG_ERROR)
+		      fprintf (dbgfp, "%s: can't set event for FD 0x%x "
+			       "(ignored)\n", log_get_prefix (NULL), fd);
+		  }
+		else
+		  {
+		    evarray[pos] = r;
+		    waitbuf[pos++] = sockevent;
+		  }
 	      }
 	    else
 	      {
@@ -1833,149 +1792,158 @@
                  log_get_prefix (NULL), i, waitbuf[i]);
     }
   n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE);
-  /* FIXME: We need to cancel all threads or keep them in a list so
-     that they are reused if we need to wait on the same event again.
-     Hmmm, that is all bullshit: We need to write a real
-     scheduler.  */
-  for (i=0; i < thlstidx; i++)
-    CloseHandle (threadlist[i]);
   if (DBG_INFO)
     fprintf (dbgfp, "%s: pth_wait: WFMO returned %ld\n",
              log_get_prefix (NULL), n);
+  count = 0;
 
-  if (n >= 0 && n < pos)
+  /* Walk over all events with an assigned handle and update the
+     status.  Note: This may override the return value of WFMO.  */
+  for (idx = 0; idx < pos; idx++)
     {
-      int count;
-      /* At least one object has been signaled.  Walk over all events
-         with an assigned handle and update the status.  We start at N
-         which indicates the lowest signaled event.  */
-      for (count = 0, idx = 0; idx < pos; idx++)
-        if (WaitForSingleObject (waitbuf[idx], 0) == WAIT_OBJECT_0)
-          {
-            r = evarray[idx];
+      r = evarray[idx];
+      
+      if (WaitForSingleObject (waitbuf[idx], 0) == WAIT_OBJECT_0)
+	{
+	  if (DBG_INFO)
+	    fprintf (dbgfp, "%s: pth_wait: setting %d ev=%p\n",
+		     __func__, idx, r);
+	  r->status = PTH_STATUS_OCCURRED;
+	  count++;
 
-            if (DBG_INFO)
-              fprintf (dbgfp, "%s: pth_wait: setting %d ev=%p\n",
-                       __func__, idx, r);
-            r->status = PTH_STATUS_OCCURRED;
-            count++;
-            switch (r->u_type)
-              {
-              case PTH_EVENT_SIGS:
-                *(r->u.sig.signo) = pth_signo;
-                break;
-              case PTH_EVENT_SELECT:
-                {
-                  struct fdarray_item_s fdarray[FD_SETSIZE];
-                  int nfdarray;
-                  WSANETWORKEVENTS ne;
-                  int ntotal = 0;
-                  unsigned long val;
-                  
-                  nfdarray = 0;
-                  nfdarray = build_fdarray (fdarray, nfdarray, 
-                                            r->u.sel.rfds, 0 );
-                  nfdarray = build_fdarray (fdarray, nfdarray, 
-                                            r->u.sel.wfds, 0 );
-                  nfdarray = build_fdarray (fdarray, nfdarray, 
-                                            r->u.sel.efds, 0 );
+	  switch (r->u_type)
+	    {
+	    case PTH_EVENT_SIGS:
+	      *(r->u.sig.signo) = pth_signo;
+	      break;
+	  
+	    case PTH_EVENT_SELECT:
+	      {
+		struct fdarray_item_s fdarray[FD_SETSIZE];
+		int nfdarray;
+		WSANETWORKEVENTS ne;
+		int ntotal = 0;
+		unsigned long val;
+		
+		nfdarray = 0;
+		nfdarray = build_fdarray (fdarray, nfdarray, r->u.sel.rfds, 0);
+		nfdarray = build_fdarray (fdarray, nfdarray, r->u.sel.wfds, 0);
+		nfdarray = build_fdarray (fdarray, nfdarray, r->u.sel.efds, 0);
+		
+		if (r->u.sel.rfds)
+		  FD_ZERO (r->u.sel.rfds);
+		if (r->u.sel.wfds)
+		  FD_ZERO (r->u.sel.wfds);
+		if (r->u.sel.efds)
+		  FD_ZERO (r->u.sel.efds);
+		for (i=0; i < nfdarray; i++)
+		  {
+		    if (WSAEnumNetworkEvents (fdarray[i].fd, NULL, &ne))
+		      {
+			if (DBG_ERROR)
+			  fprintf (dbgfp, 
+				   "%s: pth_wait: "
+				   "WSAEnumNetworkEvents(%d[%d]) failed: %s\n",
+				   log_get_prefix (NULL), i, fdarray[i].fd,
+				   wsa_strerror (strerr, sizeof strerr));
+			continue;
+		      }
+		    
+		    if (r->u.sel.rfds 
+			&& (ne.lNetworkEvents & (FD_READ|FD_ACCEPT)))
+		      {
+			FD_SET (fdarray[i].fd, r->u.sel.rfds);
+			ntotal++;
+		      }
+		    if (r->u.sel.wfds 
+			&& (ne.lNetworkEvents & (FD_WRITE)))
+		      {
+			FD_SET (fdarray[i].fd, r->u.sel.wfds);
+			ntotal++;
+		      }
+		    if (r->u.sel.efds 
+			&& (ne.lNetworkEvents & (FD_OOB|FD_CLOSE)))
+		      {
+			FD_SET (fdarray[i].fd, r->u.sel.efds);
+			ntotal++;
+		      }
+		    
+		    /* Set the socket back to blocking mode.  */
+		    /* Fixme: Do this only if the socket was in
+		       blocking mode.  */
+		    if (WSAEventSelect (fdarray[i].fd, NULL, 0))
+		      {
+			if (DBG_ERROR)
+			  fprintf (dbgfp, 
+				   "%s: pth_wait: WSAEventSelect(%d[%d]-clear)"
+				   " failed: %s\n",
+				   log_get_prefix (NULL), i, fdarray[i].fd,
+				   wsa_strerror (strerr, sizeof strerr));
+		      }
+		    
+		    val = 0;
+		    if (ioctlsocket (fdarray[i].fd, FIONBIO, &val)
+			== SOCKET_ERROR)
+		      {
+			if (DBG_ERROR)
+			  fprintf (dbgfp, 
+				   "%s: pth_wait: ioctlsocket(%d[%d])"
+				   " failed: %s\n",
+				   log_get_prefix (NULL), i, fdarray[i].fd,
+				   wsa_strerror (strerr, sizeof strerr));
+		      }
+		  }
+		*r->u.sel.rc = ntotal;
+	      }
+	      break;
+	    }
 
-                  if (r->u.sel.rfds)
-                    FD_ZERO (r->u.sel.rfds);
-                  if (r->u.sel.wfds)
-                    FD_ZERO (r->u.sel.wfds);
-                  if (r->u.sel.efds)
-                    FD_ZERO (r->u.sel.efds);
-                  for (i=0; i < nfdarray; i++)
-                    {
-                      if (WSAEnumNetworkEvents (fdarray[i].fd, NULL, &ne))
-                        {
-                          if (DBG_ERROR)
-                            fprintf (dbgfp, 
-                                   "%s: pth_wait: "
-                                   "WSAEnumNetworkEvents(%d[%d]) failed: %s\n",
-                                   log_get_prefix (NULL), i, fdarray[i].fd,
-                                   wsa_strerror (strerr, sizeof strerr));
-                          continue;
-                        }
+	  /* We don't reset Timer events and I don't know whether
+	     resetEvent will work at all.  SetWaitableTimer resets the
+	     timer.  FIXME.  Note by MB: Resetting the event here
+	     seems wrong in most (all?)  cases, as the event is still
+	     "hot" for all we know: A second pth_wait with the same
+	     events should return with the same results as the
+	     previous one immediatetly.  For example, data on a socket
+	     or pipe is still readable after.  Reset should happen in
+	     pth_read/pth_write in this case, but these functions need
+	     to do a quick poll as well.  Consider for example a
+	     pth_read_ev where multiple events occur.  See w32-io.c
+	     how this works for pipes.  FIXME: Frankly, this is a
+	     mess.  For example, make sure the below is fine with the
+	     global signal event.  Note: This is related to
+	     edge-triggered vs level-triggered.  Level triggered is
+	     doubleplusgood.  */
+	  if (r->u_type != PTH_EVENT_TIME && r->u_type != PTH_EVENT_FD)
+	    reset_event (waitbuf[idx]);
+	}
 
-                      if (r->u.sel.rfds 
-                          && (ne.lNetworkEvents & (FD_READ|FD_ACCEPT)))
-                        {
-                          FD_SET (fdarray[i].fd, r->u.sel.rfds);
-                          ntotal++;
-                        }
-                      if (r->u.sel.wfds 
-                          && (ne.lNetworkEvents & (FD_WRITE)))
-                        {
-                          FD_SET (fdarray[i].fd, r->u.sel.wfds);
-                          ntotal++;
-                        }
-                      if (r->u.sel.efds 
-                          && (ne.lNetworkEvents & (FD_OOB|FD_CLOSE)))
-                        {
-                          FD_SET (fdarray[i].fd, r->u.sel.efds);
-                          ntotal++;
-                        }
+      /* Clean up allocated resources in any case.  */
+      switch (r->u_type)
+	{
+	case PTH_EVENT_FD:
+	  {
+	    int fd = r->u.fd;
+	    int is_socket = fd_is_socket (fd);
+	    
+	    if (is_socket)
+	      {
+		WSAEventSelect (fd, NULL, 0);
+		WSACloseEvent (waitbuf[idx]);
+		waitbuf[idx] = NULL;
+	      }
+	    /* Nothing to be done for pipes.  */
+	  }
+	  break;
+	}
+    }
 
-                      /* Set the socket back to blocking mode.  */
-                      /* Fixme: Do thsi only if the socket was in
-                         blocking mode.  */
-                      if (WSAEventSelect (fdarray[i].fd, NULL, 0))
-                        {
-                          if (DBG_ERROR)
-                            fprintf (dbgfp, 
-                                 "%s: pth_wait: WSAEventSelect(%d[%d]-clear)"
-                                 " failed: %s\n",
-                                 log_get_prefix (NULL), i, fdarray[i].fd,
-                                 wsa_strerror (strerr, sizeof strerr));
-                        }
+  if (DBG_INFO)
+    fprintf (dbgfp, "%s: pth_wait: %d events have been signalled\n",
+	     log_get_prefix (NULL), count);
 
-                      val = 0;
-                      if (ioctlsocket (fdarray[i].fd, FIONBIO, &val)
-                          == SOCKET_ERROR)
-                        {
-                          if (DBG_ERROR)
-                            fprintf (dbgfp, 
-                                 "%s: pth_wait: ioctlsocket(%d[%d])"
-                                 " failed: %s\n",
-                                 log_get_prefix (NULL), i, fdarray[i].fd,
-                                 wsa_strerror (strerr, sizeof strerr));
-                        }
-
-
-                    }




More information about the Gnupg-commits mailing list