[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