[svn] assuan - r375 - trunk/src

svn author marcus cvs at cvs.gnupg.org
Wed Jun 9 15:12:32 CEST 2010


Author: marcus
Date: 2010-06-09 15:12:31 +0200 (Wed, 09 Jun 2010)
New Revision: 375

Modified:
   trunk/src/ChangeLog
   trunk/src/gpgcedev.c
Log:
2010-06-09  Marcus Brinkmann  <marcus at g10code.de>

	* gpgcedev.c (GPGCEDEV_IOCTL_UNBLOCK): New ioctl.
	(PIPE_FLAG_UNBLOCK_READER, PIPE_FLAG_UNBLOCK_WRITER): New flags.
	(GPG_Read): Check if PIPE_FLAG_UNBLOCK_READER is set and return
	ERROR_BUSY in that case.
	(GPG_Write): Likewise for PIPE_FLAG_UNBLOCK_WRITER.
	(unblock_call): New function.
	(GPG_IOControl): Implement GPGCEDEV_IOCTL_UNBLOCK.


Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2010-06-07 15:14:52 UTC (rev 374)
+++ trunk/src/ChangeLog	2010-06-09 13:12:31 UTC (rev 375)
@@ -1,3 +1,13 @@
+2010-06-09  Marcus Brinkmann  <marcus at g10code.de>
+
+	* gpgcedev.c (GPGCEDEV_IOCTL_UNBLOCK): New ioctl.
+	(PIPE_FLAG_UNBLOCK_READER, PIPE_FLAG_UNBLOCK_WRITER): New flags.
+	(GPG_Read): Check if PIPE_FLAG_UNBLOCK_READER is set and return
+	ERROR_BUSY in that case.
+	(GPG_Write): Likewise for PIPE_FLAG_UNBLOCK_WRITER.
+	(unblock_call): New function.
+	(GPG_IOControl): Implement GPGCEDEV_IOCTL_UNBLOCK.
+
 2010-06-07  Marcus Brinkmann  <marcus at g10code.de>
 
 	* gpgcedev.c: This rewrite does away with troublesome race

Modified: trunk/src/gpgcedev.c
===================================================================
--- trunk/src/gpgcedev.c	2010-06-07 15:14:52 UTC (rev 374)
+++ trunk/src/gpgcedev.c	2010-06-09 13:12:31 UTC (rev 375)
@@ -54,6 +54,17 @@
 #define GPGCEDEV_IOCTL_MAKE_PIPE \
   CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
+/* The IOCTL used to unblock a blocking thread.
+
+   The caller sends this IOCTL to the read or the write handle.  No
+   parameter is required.  The effect is that a reader or writer
+   blocked on the same handle is unblocked (and will return
+   ERROR_BUSY).  Note that the operation can be repeated, if so
+   desired.  The state of the pipe itself will not be affected in any
+   way.  */
+#define GPGCEDEV_IOCTL_UNBLOCK \
+  CTL_CODE (FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
 struct pipeimpl_s
 {
   CRITICAL_SECTION critsect;  /* Lock for all members.  */
@@ -66,6 +77,8 @@
 
 #define PIPE_FLAG_NO_READER 1
 #define PIPE_FLAG_NO_WRITER 2
+#define PIPE_FLAG_UNBLOCK_READER 4
+#define PIPE_FLAG_UNBLOCK_WRITER 8
   int flags;
 
   HANDLE space_available; /* Set if space is available.  */
@@ -488,6 +501,16 @@
 	  goto leave;
 	}
 
+      /* Check for request to unblock once.  */
+      if (pimpl->flags & PIPE_FLAG_UNBLOCK_READER)
+	{
+	  log_debug ("GPG_Read (ctx=0x%p): success: EBUSY (due to unblock request)\n", (void*)ctx);
+	  pimpl->flags &= ~PIPE_FLAG_UNBLOCK_READER;
+	  SetLastError (ERROR_BUSY);
+	  result = -1;
+	  goto leave;
+	}
+
       LeaveCriticalSection (&pimpl->critsect);
       log_debug ("GPG_Read (ctx=0x%p): waiting: data_available\n", (void*)ctx);
       WaitForSingleObject (data_available, INFINITE);
@@ -561,6 +584,16 @@
       goto leave;
     }
 
+  /* Check for request to unblock once.  */
+  if (pimpl->flags & PIPE_FLAG_UNBLOCK_WRITER)
+    {
+      log_debug ("GPG_Write (ctx=0x%p): success: EBUSY (due to unblock request)\n", (void*)ctx);
+      pimpl->flags &= ~PIPE_FLAG_UNBLOCK_WRITER;
+      SetLastError (ERROR_BUSY);
+      result = -1;
+      goto leave;
+    }
+
   /* Write to our buffer.  */
   if (pimpl->buffer_len == pimpl->buffer_size)
     {
@@ -695,6 +728,30 @@
 }
 
 
+/* opnctx_table_s is locked on entering and on exit.  */
+static BOOL
+unblock_call (opnctx_t ctx)
+{
+  /* If there is no pipe object, no thread can be blocked.  */
+  if (!ctx->pipeimpl)
+    return TRUE;
+
+  EnterCriticalSection (&ctx->pipeimpl->critsect);
+  if (ctx->access_code & GENERIC_READ)
+    {
+      ctx->pipeimpl->flags |= PIPE_FLAG_UNBLOCK_READER;
+      SetEvent (ctx->pipeimpl->data_available);
+    }
+  else if (ctx->access_code & GENERIC_WRITE)
+    {
+      ctx->pipeimpl->flags |= PIPE_FLAG_UNBLOCK_WRITER;
+      SetEvent (ctx->pipeimpl->space_available);
+    }
+  LeaveCriticalSection (&ctx->pipeimpl->critsect);
+
+  return TRUE;
+}
+
 BOOL
 GPG_IOControl (DWORD opnctx_arg, DWORD code, void *inbuf, DWORD inbuflen,
                void *outbuf, DWORD outbuflen, DWORD *actualoutlen)
@@ -754,6 +811,20 @@
         result = TRUE;
       break;
 
+    case GPGCEDEV_IOCTL_UNBLOCK:
+      log_debug ("GPG_IOControl (ctx=0x%p): code: UNBLOCK\n", (void*)opnctx);
+      if (inbuf || inbuflen || outbuf || outbuflen || actualoutlen)
+        {
+	  log_debug ("GPG_IOControl (ctx=0x%p): error: invalid parameter\n", 
+		     (void*)opnctx);
+          SetLastError (ERROR_INVALID_PARAMETER);
+          goto leave;
+        }
+      
+      if (unblock_call (opnctx))
+        result = TRUE;
+      break;
+
     case IOCTL_PSL_NOTIFY:
       log_debug ("GPG_IOControl (ctx=0x%p): code: NOTIFY\n", (void*)opnctx);
       /* Unexpected process termination.  */





More information about the Gnupg-commits mailing list