[svn] GpgOL - r242 - in trunk: . doc po src

svn author wk cvs at cvs.gnupg.org
Wed Apr 2 18:10:00 CEST 2008


Author: wk
Date: 2008-04-02 18:09:58 +0200 (Wed, 02 Apr 2008)
New Revision: 242

Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/configure.ac
   trunk/doc/gpgol.texi
   trunk/po/de.po
   trunk/po/sv.po
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/common.c
   trunk/src/engine-assuan.c
   trunk/src/engine.c
   trunk/src/main.c
   trunk/src/mimeparser.c
   trunk/src/util.h
Log:
Preparing a release


[The diff below has been truncated]

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/ChangeLog	2008-04-02 16:09:58 UTC (rev 242)
@@ -1,3 +1,7 @@
+2008-04-01  Werner Koch  <wk at g10code.com>
+
+	* configure.ac (AC_INIT): Fix quoting.
+
 2008-03-19  Werner Koch  <wk at g10code.com>
 
 	* Release 0.10.9.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/src/ChangeLog	2008-04-02 16:09:58 UTC (rev 242)
@@ -1,5 +1,23 @@
+2008-04-02  Werner Koch  <wk at g10code.com>
+
+	* engine-assuan.c (destroy_command): Add arg FORCE.
+	(op_assuan_encrypt_bottom): Call destroy_command.
+
+	* mimeparser.c (struct mime_context): Use parser_error to return
+	gpg error codes.
+
+	* main.c (read_options): Allow names for debug flags.
+	* common.c (trim_spaces): New.
+
 2008-03-31  Werner Koch  <wk at g10code.com>
 
+	* engine-assuan.c (struct work_item_s): Add SWITCH_COUNTER.
+	(switch_threads, clear_switch_threads): New.
+	(worker_start_write): Use it.
+	* engine.c (struct engine_filter_s): Add SWITCH_COUNTER.
+	(switch_threads, clear_switch_threads): New.
+	(filter_gpgme_read_cb): Use it.
+
 	* ext-commands.h (class GpgolExtCommands): Add m_nCmdCryptoState.
 	* ext-commands.cpp (InstallCommands): Add a toolbar crypto state
 	button.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/NEWS	2008-04-02 16:09:58 UTC (rev 242)
@@ -1,5 +1,13 @@
+Noteworthy changes for version 0.10.10 (2008-04-02)
+===================================================
+
+ * Visual cleanups.
+
+ * Changes to the I/O dispatcher.
+
+
 Noteworthy changes for version 0.10.9 (2008-03-19)
-=================================================
+==================================================
 
  * Decrypt opaque signed and encrypted S/MIME mails.
 
@@ -8,7 +16,7 @@
 
 
 Noteworthy changes for version 0.10.8 (2008-03-18)
-=================================================
+==================================================
 
  * Fixed a segv introduced with 0.10.6.
 

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/configure.ac	2008-04-02 16:09:58 UTC (rev 242)
@@ -16,12 +16,13 @@
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [0.10.9])
+m4_define([my_version], [0.10.10])
 m4_define([my_issvn], [no])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
             || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
-AC_INIT([gpgol], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]),
+AC_INIT([gpgol], 
+        [my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision])],
         [bug-gpgol at g10code.com])
 
 NEED_GPG_ERROR_VERSION=1.4

Modified: trunk/doc/gpgol.texi
===================================================================
--- trunk/doc/gpgol.texi	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/doc/gpgol.texi	2008-04-02 16:09:58 UTC (rev 242)
@@ -661,24 +661,26 @@
 make the log file output more verbose; these are actually bit flags
 according to the following table (which may change with any release):
 @table @code
- at item 2  (0x0002)
+ at item 2 (0x0002) (ioworker)
 Tell what the Assuan I/O scheduler is doing.
- at item 4  (0x0004)
+ at item 4 (0x0004) (ioworker-extra)
 Even more verbose Assuan I/O scheduler reporting. 
- at item 8  (0x0008)
+ at item 8  (0x0008) (filter)
 Tell what the filter I/O system is doing.
- at item 16 (0x0010)
+ at item 16 (0x0010) (filter-extra)
 Tell how the filter I/O locks the resources.
- at item 32 (0x0020)
+ at item 32 (0x0020) (memory)
 Tell about resource allocation.
- at item 64 (0x0040)
+ at item 64 (0x0040) (commands)
 Tell about command events.
- at item 128 (0x0080)
+ at item 128 (0x0080) (mime-parser)
 Tell what the MIME parser is doing
- at item 256 (0x0100)
+ at item 256 (0x0100) (mime-data)
 Print data lines while parsing MIME.
 @end table
-You may use the regular C-syntax for entering the value.
+You may use the regular C-syntax for entering the value.  As an
+alternative you may use the names ofthe flags, separated by space or
+comma.
 
 
 @itemx HKCU\Software\GNU\GpgOL:logFile

Modified: trunk/po/de.po  [not shown]
Modified: trunk/po/sv.po  [not shown]
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/src/Makefile.am	2008-04-02 16:09:58 UTC (rev 242)
@@ -74,13 +74,13 @@
 	$(DLLTOOL) --output-lib $@ --def $<
 
 libgpg-error.a:
-	ln -s $(shell $(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a
+	ln -s $$($(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a .
 
 libgpgme.a:
-	ln -s $(shell $(GPGME_CONFIG) --prefix)/lib/libgpgme.a
+	ln -s $$($(GPGME_CONFIG) --prefix)/lib/libgpgme.a .
 
 libassuan.a:
-	ln -s $(shell $(LIBASSUAN_CONFIG) --prefix)/lib/libassuan.a
+	ln -s $$($(LIBASSUAN_CONFIG) --prefix)/lib/libassuan.a .
 
 clean-local:
 	rm -f libmapi32.a libgpg-error.a libgpgme.a libassuan.a

Modified: trunk/src/common.c
===================================================================
--- trunk/src/common.c	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/src/common.c	2008-04-02 16:09:58 UTC (rev 242)
@@ -413,6 +413,36 @@
 }
 
 
+/* Strip off leading and trailing white spaces from STRING.  Returns
+   STRING. */
+char *
+trim_spaces (char *arg_string)
+{
+  char *string = arg_string;
+  char *p, *mark;
+
+  /* Find first non space character. */
+  for (p = string; *p && isascii (*p) && isspace (*p) ; p++ )
+    ;
+  /* Move characters. */
+  for (mark = NULL; (*string = *p); string++, p++ )
+    {
+      if (isascii (*p) && isspace (*p))
+        {
+          if (!mark)
+          mark = string;
+        }
+      else
+        mark = NULL ;
+    }
+  if (mark)
+    *mark = 0;
+  
+  return arg_string;
+}
+
+
+
 /* Helper for read_w32_registry_string(). */
 static HKEY
 get_root_key(const char *root)

Modified: trunk/src/engine-assuan.c
===================================================================
--- trunk/src/engine-assuan.c	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/src/engine-assuan.c	2008-04-02 16:09:58 UTC (rev 242)
@@ -111,6 +111,8 @@
                                     queue.  */
   OVERLAPPED ov;     /* The overlapped info structure.  */
   char buffer[1024]; /* The buffer used by ReadFile or WriteFile.  */
+
+  ULONG switch_counter; /* Used by switch_threads.  */
 };
 
 
@@ -636,6 +638,39 @@
 #endif /* not used.  */
 
 
+/* This is a wraper around SwitchToThread, a syscall we unfortunately
+   need due to the lack of an sophisticated event system.  The wrapper
+   calls SwitchToThread but after a couple of immediate folliwing
+   switches, it introduces a short delays.  */
+static void
+switch_threads (work_item_t item)
+{
+  ULONG count;
+
+  count = InterlockedExchangeAdd (&item->switch_counter, 1);
+  if (count > 5)
+    {
+      /* Tried too often without success.  Use Sleep until
+         clear_switch_threads has been called.  */
+      InterlockedExchange (&item->switch_counter, 5);
+      SleepEx (60, TRUE); 
+    }
+  else if (!SwitchToThread ())
+    {
+      /* No runable other thread: Fall asleep. */
+      SleepEx (8, TRUE);
+    }
+}
+
+/* Call this fucntion if some action has been done.  */
+static void
+clear_switch_threads (work_item_t item)
+{
+  InterlockedExchange (&item->switch_counter, 0);
+}
+
+
+
 
 /* Helper for async_worker_thread.  Returns true if the item's handle
    needs to be put on the wait list.  This is called with the worker
@@ -763,13 +798,16 @@
   /* Read from the callback and the write to the handle.  The gpgme
      callback is expected to never block.  */
   nread = gpgme_data_read (item->data, item->buffer, sizeof item->buffer);
+  if (nread < 0 && errno == EAGAIN)
+    switch_threads (item);
+  else
+    clear_switch_threads (item);
   if (nread < 0)
     {
       if (errno == EAGAIN)
         {
 /*           log_debug ("%s:%s: [%s:%p] ignoring EAGAIN from callback", */
 /*                      SRCNAME, __func__, item->name, item->hd); */
-          SwitchToThread ();
           retval = 1;
         }
       else
@@ -955,7 +993,21 @@
 /*                                          INFINITE, QS_ALLEVENTS); */
           if (n == WAIT_FAILED)
             {
+              int i;
+              DWORD hdinfo;
+                  
               log_error_w32 (-1, "%s:%s: WFMO failed", SRCNAME, __func__);
+              for (i=0; i < hdarraylen; i++)
+                {
+                  hdinfo = 0;
+                  if (!GetHandleInformation (hdarray[i], &hdinfo))
+                    log_debug_w32 (-1, "%s:%s: WFMO GetHandleInfo(%p) failed", 
+                                   SRCNAME, __func__, hdarray[i]);
+                  else
+                    log_debug ("%s:%s: WFMO GetHandleInfo(%p)=0x%lu", 
+                               SRCNAME, __func__, hdarray[i],
+                               (unsigned long)hdinfo);
+                }
               Sleep (1000);
             }
           else if (n >= 0 && n < hdarraylen)
@@ -1060,33 +1112,60 @@
             {
               if (item->cld)
                 {
+                  work_item_t itm2;
+
                   if (!item->cld->final_err && item->got_error)
                     item->cld->final_err = gpg_error (GPG_ERR_EIO);
 
-                  if (!item->cld->final_err)
+                  /* Check whether there are other work items in this
+                     group we need to wait for before invoking the
+                     closure. */
+                  for (itm2=work_queue; itm2; itm2 = itm2->next)
+                    if (itm2->used && itm2 != item 
+                        && itm2->cmdid == item->cmdid
+                        && itm2->wait_on_success
+                        && !(itm2->got_ready || itm2->got_error))
+                      break;
+                  if (itm2)
                     {
-                      /* Check whether there are other work items in
-                         this group we need to wait for before
-                         invoking the closure. */
-                      work_item_t itm2;
-                      
-                      for (itm2=work_queue; itm2; itm2 = itm2->next)
-                        if (itm2->used && itm2 != item 
-                            && itm2->cmdid == item->cmdid
-                            && itm2->wait_on_success
-                            && !(itm2->got_ready || itm2->got_error))
-                          break;
-                      if (itm2)
+                      if (debug_ioworker)
+                        log_debug ("%s:%s: [%s:%p] delaying closure "
+                                   "due to [%s:%p]", SRCNAME, __func__,
+                                   item->name, item->hd, 
+                                   itm2->name, itm2->hd);
+                      item->delayed_ready = 1;
+                      if (item->cld->final_err)
                         {
-                          if (debug_ioworker)
-                            log_debug ("%s:%s: [%s:%p] delaying closure "
-                                       "due to [%s/%p]", SRCNAME, __func__,
-                                       item->name, item->hd, 
-                                       itm2->name, itm2->hd);
-                          item->delayed_ready = 1;
-                          break; 
+                          /* If we received an error we better do not
+                             assume that the server has properly
+                             closed all I/O channels.  Send a cancel
+                             to the work item we are waiting for. */
+                          if (!itm2->aborting)
+                            {
+                              if (debug_ioworker)
+                                log_debug ("%s:%s: [%s:%p] calling CancelIO",
+                                           SRCNAME, __func__,
+                                           itm2->name, itm2->hd);
+                              itm2->aborting = 1;
+                              if (!CancelIo (itm2->hd))
+                                log_error_w32 (-1, "%s:%s: [%s:%p] "
+                                               "CancelIo failed",
+                                               SRCNAME,__func__, 
+                                               itm2->name, itm2->hd);
+                            }
+                          else
+                            {
+                              if (debug_ioworker)
+                                log_debug ("%s:%s: [%s:%p] clearing "
+                                           "wait on success flag",
+                                           SRCNAME, __func__,
+                                           itm2->name, itm2->hd);
+                              itm2->wait_on_success = 0;
+                            }
                         }
+                      break; 
                     }
+
                   item->delayed_ready = 0;
                   if (debug_ioworker)
                     log_debug ("%s:%s: [%s:%p] invoking closure",
@@ -1189,18 +1268,19 @@
 /* Remove all items from the work queue belonging to the command with
    the id CMDID.  */
 static void
-destroy_command (ULONG cmdid)
+destroy_command (ULONG cmdid, int force)
 {
   work_item_t item;
 
   EnterCriticalSection (&work_queue_lock);
   for (item = work_queue; item; item = item->next)
-    if (item->used && item->cmdid == cmdid && !item->wait_on_success)
+    if (item->used && item->cmdid == cmdid 
+        && (!item->wait_on_success || force))
       {
         if (debug_ioworker)
           log_debug ("%s:%s: [%s:%p] cmdid=%lu registered for destroy",
                      SRCNAME, __func__, item->name, item->hd, item->cmdid);
-        /* First send an I/O cancel in case the the last
+        /* First send an I/O cancel in case the last
            GetOverlappedResult returned only a partial result.  This
            works because we are always running within the
            async_worker_thread.  */
@@ -1315,7 +1395,7 @@
               break;
             case 1: /* Ready. */
               cld->status_ready = 1;
-              destroy_command (cld->cmdid);
+              destroy_command (cld->cmdid, 0);
               break;
             default:
               log_error ("%s:%s: invalid line from server", SRCNAME, __func__);
@@ -1432,7 +1512,7 @@
    correct relationship between a popups and the active window.  If
    this function returns success, the data objects may only be
    destroyed after an engine_wait or engine_cancel.  On success the
-   fucntion returns a pojunter to the encryption state and thus
+   function returns a poiunter to the encryption state and thus
    requires that op_assuan_encrypt_bottom will be run later. */
 int
 op_assuan_encrypt (protocol_t protocol, 
@@ -1579,11 +1659,15 @@
 
   if (err)
     {
-      /* Fixme: Cancel stuff in the work_queue. */
+      xfree (encstate->cld);
+      encstate->cld = NULL;
+      engine_private_set_cancel (encstate->filter, NULL);
       close_pipe (encstate->inpipe);
       close_pipe (encstate->outpipe);
-      xfree (encstate->cld);
+      if (cancel)
+        destroy_command (encstate->cmdid, 1);
       assuan_disconnect (encstate->ctx);
+      encstate->ctx = NULL;
     }
   else
     engine_private_set_cancel (encstate->filter, encstate->ctx);

Modified: trunk/src/engine.c
===================================================================
--- trunk/src/engine.c	2008-03-31 16:29:54 UTC (rev 241)
+++ trunk/src/engine.c	2008-04-02 16:09:58 UTC (rev 242)
@@ -105,6 +105,9 @@
   /* A pointer used convey information from engine_encrypt_prepare to
      engine_encrypt_start.  */
   struct engine_assuan_encstate_s *encstate;
+
+  /* Counter used to optimize voluntary thread switching. */
+  ULONG switch_counter;
 };
 
 
@@ -198,8 +201,36 @@
 }
 
 
+/* This is a wraper around SwitchToThread, a syscall we unfortunately
+   need due to the lack of an sophisticated event system.  The wrapper
+   calls SwitchToThread but after a couple of immediate folliwing
+   switches, it introduces a short delays.  */
+static void
+switch_threads (engine_filter_t filter)
+{
+  ULONG count;
 
+  count = InterlockedExchangeAdd (&filter->switch_counter, 1);
+  if (count > 5)
+    {
+      InterlockedExchange (&filter->switch_counter, 5);
+      SleepEx (50, TRUE); 
+    }
+  else if (!SwitchToThread ())
+    {
+      /* No runable other thread: Fall asleep. */
+      SleepEx (5, TRUE);
+    }
+}
 
+/* Call this fucntion if some action has been done.  */
+static void
+clear_switch_threads (engine_filter_t filter)
+{
+  InterlockedExchange (&filter->switch_counter, 0);
+}
+
+
 /* This read callback is used by GPGME to read data from a filter
    object.  The function should return the number of bytes read, 0 on
    EOF, and -1 on error.  If an error occurs, ERRNO should be set to
@@ -234,9 +265,11 @@
           errno = EAGAIN;
           if (debug_filter_extra)
             log_debug ("%s:%s: leave; result=EAGAIN\n", SRCNAME, __func__);
-          SwitchToThread ();
+          switch_threads (filter);
           return -1;
         }
+      else
+        clear_switch_threads (filter);
       if (debug_filter)
         log_debug ("%s:%s: waiting for in.condvar\n", SRCNAME, __func__);
       WaitForSingleObject (filter->in.condvar, 500);
@@ -425,8 +458,11 @@
                SRCNAME, __func__, indata, (int)indatalen, filter->outfnc); 
   for (;;)
     {
+      int any;
+
       /* If there is something to write out, do this now to make space
          for more data.  */
+      any = 0;
       take_out_lock (filter, __func__);
       while (filter->out.length)
         {
@@ -447,13 +483,19 @@
             memmove (filter->out.buffer, filter->out.buffer + nbytes,
                      filter->out.length - nbytes); 
           filter->out.length -= nbytes;
+          any = 1;
         }
       if (!PulseEvent (filter->out.condvar))
         log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__);
       release_out_lock (filter, __func__);
-      
+
+      if (any)
+        clear_switch_threads (filter);
+      else
+        switch_threads (filter);
+
+      any = 0;
       take_in_lock (filter, __func__);
-
       if (!indata && !indatalen)
         {
           filter->in.got_eof = 1;
@@ -480,17 +522,23 @@
           memcpy (filter->in.buffer, indata, filter->in.length);
           indata    += filter->in.length;
           indatalen -= filter->in.length;
+          any = 1;
         }
+      /* Terminate the loop if the filter queue is empty OR the filter
+         is ready and there is nothing left for output.  */
       if (!filter->in.length || (filter->in.ready && !filter->out.length))
         {
           release_in_lock (filter, __func__);




More information about the Gnupg-commits mailing list