[svn] gpgme - r1454 - trunk/src

svn author wk cvs at cvs.gnupg.org
Wed Feb 17 22:40:02 CET 2010


Author: wk
Date: 2010-02-17 22:40:02 +0100 (Wed, 17 Feb 2010)
New Revision: 1454

Modified:
   trunk/src/ChangeLog
   trunk/src/posix-io.c
Log:
Changed the close notify implementaion to allow for more than 256 fds.
We should write a test case for it, though.


Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2010-02-16 20:07:03 UTC (rev 1453)
+++ trunk/src/ChangeLog	2010-02-17 21:40:02 UTC (rev 1454)
@@ -1,3 +1,10 @@
+2010-02-17  Werner Koch  <wk at g10code.com>
+
+	* posix-io.c (notify_table): Change implementation.
+	(notify_table_item_t, notify_table_size, notify_table_lock): New.
+	(_gpgme_io_close, _gpgme_io_set_close_notify): Adjust for new
+	implementation.
+
 2010-02-16  Werner Koch  <wk at g10code.com>
 
 	* gpgme-tool.c (spacep, has_option, skip_options): New.

Modified: trunk/src/posix-io.c
===================================================================
--- trunk/src/posix-io.c	2010-02-16 20:07:03 UTC (rev 1453)
+++ trunk/src/posix-io.c	2010-02-17 21:40:02 UTC (rev 1454)
@@ -1,6 +1,6 @@
 /* posix-io.c - Posix I/O functions
    Copyright (C) 2000 Werner Koch (dd9jn)
-   Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH
+   Copyright (C) 2001, 2002, 2004, 2005, 2007, 2010 g10 Code GmbH
 
    This file is part of GPGME.
  
@@ -15,9 +15,8 @@
    Lesser General Public License for more details.
    
    You should have received a copy of the GNU Lesser General Public
-   License along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -73,13 +72,22 @@
 }
 
 
-static struct
+/* The table to hold notification handlers.  We use a linear search
+   and extend the table as needed.  */
+struct notify_table_item_s
 {
+  int fd;  /* -1 indicates an unused entry.  */
   _gpgme_close_notify_handler_t handler;
   void *value;
-} notify_table[256];
+};
+typedef struct notify_table_item_s *notify_table_item_t;
 
+static notify_table_item_t notify_table;
+static size_t notify_table_size;
+DEFINE_STATIC_LOCK (notify_table_lock);
 
+
+
 int
 _gpgme_io_read (int fd, void *buffer, size_t count)
 {
@@ -149,6 +157,9 @@
 _gpgme_io_close (int fd)
 {
   int res;
+  _gpgme_close_notify_handler_t handler = NULL;
+  void *handler_value;
+  int idx;
 
   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
 
@@ -159,17 +170,26 @@
     }
 
   /* First call the notify handler.  */
-  if (fd >= 0 && fd < (int) DIM (notify_table))
+  LOCK (notify_table_lock);
+  for (idx=0; idx < notify_table_size; idx++)
     {
-      if (notify_table[fd].handler)
-	{
-	  TRACE_LOG2 ("invoking close handler %p/%p",
-		      notify_table[fd].handler, notify_table[fd].value);
-	  notify_table[fd].handler (fd, notify_table[fd].value);
-	  notify_table[fd].handler = NULL;
-	  notify_table[fd].value = NULL;
+      if (notify_table[idx].fd == fd)
+        {
+	  handler       = notify_table[idx].handler;
+	  handler_value = notify_table[idx].value;
+	  notify_table[idx].handler = NULL;
+	  notify_table[idx].value = NULL;
+	  notify_table[idx].fd = -1; /* Mark slot as free.  */
+          break;
         }
     }
+  UNLOCK (notify_table_lock);
+  if (handler)
+    {
+      TRACE_LOG2 ("invoking close handler %p/%p", handler, handler_value);
+      handler (fd, handler_value);
+    }
+
   /* Then do the close.  */    
   res = close (fd);
   return TRACE_SYSRES (res);
@@ -180,19 +200,52 @@
 _gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
 			    void *value)
 {
+  int res = 0;
+  int idx;
+
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
 	      "close_handler=%p/%p", handler, value);
 
   assert (fd != -1);
+  
+  LOCK (notify_table_lock);
+  for (idx=0; idx < notify_table_size; idx++)
+    if (notify_table[idx].fd == -1)
+      break;
+  if (idx == notify_table_size)
+    {
+      /* We need to increase the size of the table.  The approach we
+         take is straightforward to minimize the risk of bugs.  */
+      notify_table_item_t newtbl;
+      size_t newsize = notify_table_size + 64;
 
-  if (fd < 0 || fd >= (int) DIM (notify_table))
-    {
-      errno = EINVAL;
-      return TRACE_SYSRES (-1);
+      newtbl = calloc (newsize, sizeof *newtbl);
+      if (!newtbl)
+        {
+          res = -1;
+          goto leave;
+        }
+      for (idx=0; idx < notify_table_size; idx++)
+        newtbl[idx] = notify_table[idx];
+      for (; idx < newsize; idx++)
+        {
+          newtbl[idx].fd = -1;
+          newtbl[idx].handler = NULL;
+          newtbl[idx].value = NULL;
+        }
+      free (notify_table);
+      notify_table = newtbl;
+      idx = notify_table_size;
+      notify_table_size = newsize;
     }
-  notify_table[fd].handler = handler;
-  notify_table[fd].value = value;
-  return TRACE_SYSRES (0);
+  notify_table[idx].fd = fd;
+  notify_table[idx].handler = handler;
+  notify_table[idx].value = value;
+  
+ leave:
+  UNLOCK (notify_table_lock);
+
+  return TRACE_SYSRES (res);
 }
 
 




More information about the Gnupg-commits mailing list