2007-10-04 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Thu, 4 Oct 2007 14:09:58 +0000 (14:09 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 4 Oct 2007 14:09:58 +0000 (14:09 +0000)
* kdpipeiodevice.h, kdpipeiodevice.cpp, kdpipeiodevice.moc,
w32-qt-io.cpp: New versions from Frank Osterfeld.

gpgme/ChangeLog
gpgme/kdpipeiodevice.cpp
gpgme/kdpipeiodevice.h
gpgme/kdpipeiodevice.moc
gpgme/w32-qt-io.cpp

index 9b724657c73445b180ae18318a2d0543b1765411..77de5ea0d307d0029aedfa63171f6a454b50acc4 100644 (file)
@@ -1,3 +1,8 @@
+2007-10-04  Marcus Brinkmann  <marcus@g10code.de>
+
+       * kdpipeiodevice.h, kdpipeiodevice.cpp, kdpipeiodevice.moc,
+       w32-qt-io.cpp: New versions from Frank Osterfeld.
+
 2007-10-02  Marcus Brinkmann  <marcus@g10code.de>
 
        * kdpipeiodevice.cpp, kdpipeiodevice.moc: New versions.
index 0cd4ef8e2a422b2b86b47b1752a9efdc25ae7d4e..1fd0ef02646544e3c8647e4e25cd95b000ff89cb 100644 (file)
@@ -99,14 +99,14 @@ public:
     QWaitCondition bufferNotEmptyCondition;
     QWaitCondition hasStarted;
     QWaitCondition readyReadSentCondition;
-    QWaitCondition notInReadDataCondition;
+    QWaitCondition blockedConsumerIsDoneCondition;
     bool cancel;
     bool eof;
     bool error;
     bool eofShortCut;
     int errorCode;
-    bool inReadData; 
-
+    bool consumerBlocksOnUs;
+   
 private:
     unsigned int rptr, wptr;
     char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state
@@ -127,7 +127,7 @@ Reader::Reader( int fd_, Qt::HANDLE handle_ )
       eofShortCut( false ),
       errorCode( 0 ),
       rptr( 0 ), wptr( 0 ),
-      inReadData( false )
+      consumerBlocksOnUs( false )
 {
     
 }
@@ -226,13 +226,13 @@ KDPipeIODevice::Private::Private( KDPipeIODevice * qq )
       handle( 0 ),
       reader( 0 ),
       writer( 0 ),
-      triedToStartReader( false ), triedToStartWriter( false )
+      triedToStartReader( false ), triedToStartWriter( false ) 
 {
 
 }
 
 KDPipeIODevice::Private::~Private() {
-    qDebug( "KDPipeIODevice::~Private(): Destroying %p", this );
+    qDebug( "KDPipeIODevice::~Private(): Destroying %p", q );
 }
 
 KDPipeIODevice::KDPipeIODevice( QObject * p )
@@ -290,11 +290,15 @@ bool KDPipeIODevice::Private::startReaderThread()
        return true;
    triedToStartReader = true;    
    if ( reader && !reader->isRunning() && !reader->isFinished() ) {
+       qDebug("KDPipeIODevice::Private::startReaderThread(): locking reader (CONSUMER THREAD)" );
        LOCKED( reader );
-       
+       qDebug("KDPipeIODevice::Private::startReaderThread(): locked reader (CONSUMER THREAD)" );
        reader->start( QThread::HighestPriority );
-       if ( !reader->hasStarted.wait( &reader->mutex, 1000 ) )
-            return false;
+       qDebug("KDPipeIODevice::Private::startReaderThread(): waiting for hasStarted (CONSUMER THREAD)" );
+       const bool hasStarted = reader->hasStarted.wait( &reader->mutex, 1000 );
+       qDebug("KDPipeIODevice::Private::startReaderThread(): returned from hasStarted (CONSUMER THREAD)" );
+
+       return hasStarted;
    }
    return true;
 }
@@ -320,11 +324,16 @@ void KDPipeIODevice::Private::emitReadyRead()
     const int counter = s_counter++;
     QPointer<Private> thisPointer( this );
     qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d", this, counter );
+
     emit q->readyRead();
+
     if ( !thisPointer )
        return;
-    LOCKED( reader );
-    reader->readyReadSentCondition.wakeAll();
+    qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d: locking reader (CONSUMER THREAD)", this, counter );
+    synchronized( reader ) {
+        qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d: locked reader (CONSUMER THREAD)", this, counter );
+        reader->readyReadSentCondition.wakeAll();
+    }
     qDebug( "KDPipeIODevice::Private::emitReadyRead %p leaving %d", this, counter );
 
 }
@@ -342,8 +351,6 @@ bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode
     if ( !(mode_ & ReadWrite) )
        return false; // need to have at least read -or- write
 
-    fd = fd_;
-    handle = handle_;
 
     std::auto_ptr<Reader> reader_;
     std::auto_ptr<Writer> writer_;
@@ -387,7 +394,10 @@ qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS;
          return base;
     }
     if ( d->reader )
-       synchronized( d->reader ) return base + d->reader->bytesInBuffer();
+       synchronized( d->reader ) {
+            const qint64 inBuffer = d->reader->bytesInBuffer();     
+            return base + inBuffer;
+       }
     return base;
 }
 
@@ -445,6 +455,7 @@ bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS;
 }
 
 bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
+    qDebug( "KDPipeIODEvice::waitForReadyRead()(%p)", this);
     d->startReaderThread();
     if ( ALLOW_QIODEVICE_BUFFERING ) {
        if ( bytesAvailable() > 0 )
@@ -454,7 +465,10 @@ bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
     if ( !r || r->eofShortCut )
        return true;
     LOCKED( r );
-    return r->bytesInBuffer() != 0 || r->eof || r->error || r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ;
+    if ( r->bytesInBuffer() != 0 || r->eof || r->error )
+        return true;
+    assert( false );
+    return r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ;
 }
 
 template <typename T>
@@ -467,6 +481,22 @@ private:
    const T oldValue;
 }; 
 
+
+bool KDPipeIODevice::readWouldBlock() const
+{
+   d->startReaderThread();
+   LOCKED( d->reader );
+   return d->reader->bufferEmpty() && !d->reader->eof && !d->reader->error;
+}  
+
+bool KDPipeIODevice::writeWouldBlock() const
+{
+   d->startWriterThread();
+   LOCKED( d->writer );
+   return d->writer->bufferFull() && !d->writer->error;
+}  
+
+
 qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS;
     qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, data, maxSize );
     d->startReaderThread();
@@ -491,15 +521,17 @@ qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS
        if ( bytesAvailable() > 0 )
            maxSize = std::min( maxSize, bytesAvailable() ); // don't block
     }
-  
+    qDebug( "%p: KDPipeIODevice::readData: try to lock reader (CONSUMER THREAD)" );
     LOCKED( r );
-    const TemporaryValue<bool> tmp( d->reader->inReadData, true );
-    assert( d->reader->inReadData );
-    while ( /* maxSize > 0 && */ r->bufferEmpty() &&  !r->error && !r->eof ) { // ### block on maxSize == 0?
-       qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition", this );
-        r->readyReadSentCondition.wakeAll();
-        r->notInReadDataCondition.wakeAll(); 
+    qDebug( "%p: KDPipeIODevice::readData: locked reader (CONSUMER THREAD)" );
+
+    r->readyReadSentCondition.wakeAll();
+    if ( /* maxSize > 0 && */ r->bufferEmpty() &&  !r->error && !r->eof ) { // ### block on maxSize == 0?
+       qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition (CONSUMER THREAD)", this );
+        const TemporaryValue<bool> tmp( d->reader->consumerBlocksOnUs, true );
        r->bufferNotEmptyCondition.wait( &r->mutex );
+        r->blockedConsumerIsDoneCondition.wakeAll();
+       qDebug( "%p: KDPipeIODevice::readData: woke up from bufferNotEmptyCondition (CONSUMER THREAD)", this ); 
     }
 
     if ( r->bufferEmpty() ) {
@@ -507,7 +539,6 @@ qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS
        // woken with an empty buffer must mean either EOF or error:
        assert( r->eof || r->error );
        r->eofShortCut = true;
-        r->notInReadDataCondition.wakeAll();
        return r->eof ? 0 : -1 ;
     }
 
@@ -515,7 +546,7 @@ qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS
     const qint64 bytesRead = r->readData( data, maxSize );
     qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead );
     qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data );
-    r->notInReadDataCondition.wakeAll();
     return bytesRead;
 }
 
@@ -590,13 +621,14 @@ void KDPipeIODevice::Private::stopThreads()
         assert( q->bytesToWrite() == 0 );
     }
     if ( Reader * & r = reader ) {
+        disconnect( r, SIGNAL( readyRead() ), this, SLOT( emitReadyRead() ) ); 
        synchronized( r ) {
            // tell thread to cancel:
            r->cancel = true;
            // and wake it, so it can terminate:
            r->bufferNotFullCondition.wakeAll();
             r->readyReadSentCondition.wakeAll();
-       }
+       }
     }
     if ( Writer * & w = writer ) {
        synchronized( w ) {
@@ -617,10 +649,14 @@ void KDPipeIODevice::close() { KDAB_CHECK_THIS;
     emit aboutToClose();
     d->stopThreads();
 
-#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* t2 = t; t = 0; delete t2; }
+#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* const t2 = t; t = 0; delete t2; }
     qDebug( "KPipeIODevice::close(%p): wait and closing writer %p", this, d->writer );
     waitAndDelete( d->writer );
     qDebug( "KPipeIODevice::close(%p): wait and closing reader %p", this, d->reader );
+    {
+        LOCKED( d->reader );
+        d->reader->readyReadSentCondition.wakeAll();
+    }
     waitAndDelete( d->reader );
 #undef waitAndDelete
 #ifdef Q_OS_WIN32
@@ -645,115 +681,102 @@ void Reader::run() {
     qDebug( "%p: Reader::run: started", this );
 
     while ( true ) {
-
-       if ( !bufferFull() && !bufferEmpty() ) {
+        if ( !cancel && ( eof || error ) ) {
+           qDebug( "%p: Reader::run: received eof(%d) or error(%d), waking everyone", this, eof, error );
+            notifyReadyRead();
+        } else if ( !cancel && !bufferFull() && !bufferEmpty() ) {
            qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this );
             notifyReadyRead();
         } 
  
-        while ( !cancel && bufferFull() ) {
-            bufferNotEmptyCondition.wakeAll();
+        while ( !error && !cancel && bufferFull() ) {
             notifyReadyRead();
-            if ( !bufferFull() )
-               break;
-            qDebug( "%p: Reader::run: buffer is full, going to sleep", this );
-           bufferNotFullCondition.wait( &mutex );
-           qDebug( "%p: Reader::run: woke up", this );
-       }
+            if ( bufferFull() ) {
+                qDebug( "%p: Reader::run: buffer is full, going to sleep", this );
+               bufferNotFullCondition.wait( &mutex );
+           }
+        }
         
        if ( cancel ) {
-           qDebug( "%p: Reader::run: detected cancel", this );
+            qDebug( "%p: Reader::run: detected cancel", this );
            goto leave;
        }
 
+        if ( !eof && !error ) {
+            if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty
+               rptr = wptr = 0;
 
-       if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty
-           rptr = wptr = 0;
-
-       unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer;
-       if ( numBytes > sizeof buffer - wptr )
-           numBytes = sizeof buffer - wptr;
+            unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer;
+           if ( numBytes > sizeof buffer - wptr )
+               numBytes = sizeof buffer - wptr;
 
-       qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes );
+           qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes );
 
-       assert( numBytes > 0 );
+           assert( numBytes > 0 );
 
-       qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes );
+           qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes );
 #ifdef Q_OS_WIN32
-       DWORD numRead;
-       mutex.unlock();
-       const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 );
-       mutex.lock();
-       if ( !ok ) {
-           errorCode = static_cast<int>( GetLastError() );
-           if ( errorCode == ERROR_BROKEN_PIPE ) {
-                assert( numRead == 0 );
-               qDebug( "%p: Reader::run: got eof (broken pipe)", this );
-               eof = true;
-           } else {
-                assert( numRead == 0 );
-               qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode );
-               error = true;
+           mutex.unlock();
+            DWORD numRead;
+           const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 );
+           mutex.lock();
+           if ( !ok ) {
+               errorCode = static_cast<int>( GetLastError() );
+               if ( errorCode == ERROR_BROKEN_PIPE ) {
+                    assert( numRead == 0 );
+                    qDebug( "%p: Reader::run: got eof (broken pipe)", this );
+                   eof = true;
+               } else {
+                    assert( numRead == 0 );
+                   qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode );
+                   error = true;
+               }
            }
-           goto leave;
-       }
 #else
-       qint64 numRead;
-       mutex.unlock();
-       do {
-           numRead = ::read( fd, buffer + wptr, numBytes );
-       } while ( numRead == -1 && errno == EINTR );
-       mutex.lock();
-
-       if ( numRead < 0 ) {
-           errorCode = errno;
-           error = true;
-           qDebug( "%p: Reader::run: got error: %d", this, errorCode );
-           goto leave;
-       }
-#endif
-       qDebug( "%p: Reader::run: read %ld bytes", this, static_cast<long>(numRead) );
-       qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, fd, buffer );
-       if ( numRead == 0 ) {
-           qDebug( "%p: Reader::run: eof detected", this );
-           eof = true;
-           goto leave;
-       }
+           qint64 numRead;
+           mutex.unlock();
+           do {
+               numRead = ::read( fd, buffer + wptr, numBytes );
+           } while ( numRead == -1 && errno == EINTR );
+           mutex.lock();
 
-       if ( cancel ) {
-           qDebug( "%p: Reader::run: detected cancel", this );
-           goto leave;
-       }
-       qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr );
-       wptr = ( wptr + numRead ) % sizeof buffer;
-       qDebug( "%p: Reader::run: buffer after:  rptr=%4d, wptr=%4d", this, rptr, wptr );
+           if ( numRead < 0 ) {
+               errorCode = errno;
+               error = true;
+               qDebug( "%p: Reader::run: got error: %d", this, errorCode );
+            } else if ( numRead == 0 ) {
+               qDebug( "%p: Reader::run: eof detected", this );  
+                eof = true;
+            }
+#endif
+           qDebug( "%p: Reader::run: read %ld bytes", this, static_cast<long>(numRead) );
+           qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, fd, buffer );
+
+           if ( numRead > 0 ) {
+               qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr );
+               wptr = ( wptr + numRead ) % sizeof buffer;
+               qDebug( "%p: Reader::run: buffer after:  rptr=%4d, wptr=%4d", this, rptr, wptr );
+            }
+        }
     }
  leave:
-    qDebug( "%p: Reader::run: terminating: loop while not canceled and not empty", this );
-    while ( !cancel && !bufferEmpty() ) {
-        notifyReadyRead();
-    } 
-    notifyReadyRead();
     qDebug( "%p: Reader::run: terminated", this );
 }
 
 void Reader::notifyReadyRead()
 {
-    qDebug( "notifyReadyRead" );
-    if ( cancel )
-        return;   
-    bufferNotEmptyCondition.wakeAll();
-    if ( inReadData ) {
-        qDebug( "notifyReadyRead: inReadData: waiting" ); 
-        notInReadDataCondition.wait( &mutex );
+    qDebug( "notifyReadyRead: %d bytes available", bytesInBuffer() );
+    assert( !cancel );
+
+    if ( consumerBlocksOnUs ) {
+        bufferNotEmptyCondition.wakeAll();
+        blockedConsumerIsDoneCondition.wait( &mutex );
+        return;
     }
-    if ( cancel || ( !eof && !error && bufferEmpty() ) )
-        return; 
-    qDebug( "readyReadData: actually emit signal" );
+    qDebug( "notifyReadyRead: emit signal" );
     emit readyRead();
-    bufferNotEmptyCondition.wakeAll();
     readyReadSentCondition.wait( &mutex );
-    bufferNotEmptyCondition.wakeAll();
+    qDebug( "notifyReadyRead: returning from waiting, leave" );
 }
 
 void Writer::run() {
@@ -796,7 +819,7 @@ void Writer::run() {
                errorCode = static_cast<int>( GetLastError() );
                qDebug( "%p: Writer::run: got error code: %d", this, errorCode );
                error = true;
-               goto leave;
+                goto leave;
            }
 #else
            qint64 numWritten;
@@ -805,17 +828,17 @@ void Writer::run() {
            } while ( numWritten == -1 && errno == EINTR );
 
            if ( numWritten < 0 ) {
-               mutex.lock();
+               mutex.lock();
                errorCode = errno;
                qDebug( "%p: Writer::run: got error code: %d", this, errorCode );
                error = true;
-               goto leave;
+                goto leave;
            }
 #endif
             qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer,
 buffer );
            totalWritten += numWritten;
-           mutex.lock();
+            mutex.lock();
        } while ( totalWritten < numBytesInBuffer );
 
        qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten );
index f2eab52dc713fe5512303d1da80d0bd02c844b75..8da6af684accf90640a541be57690036b6f7efe4 100644 (file)
@@ -45,6 +45,9 @@ public:
     Qt::HANDLE handle() const;
     int descriptor() const;
 
+    bool readWouldBlock() const;
+    bool writeWouldBlock() const;
+
     /* reimp */ qint64 bytesAvailable() const;
     /* reimp */ qint64 bytesToWrite() const;
     /* reimp */ bool canReadLine() const;
index b29389003f9f82690da72778b43c378975f43072..457f371ad935bab21256e60ea5a8c586fecdba7c 100644 (file)
@@ -1,7 +1,7 @@
 /****************************************************************************
 ** Meta object code from reading C++ file 'kdpipeiodevice.cpp'
 **
-** Created: Mon Oct 1 16:08:44 2007
+** Created: Tue Oct 2 19:30:13 2007
 **      by: The Qt Meta Object Compiler version 59 (Qt 4.3.1)
 **
 ** WARNING! All changes made in this file will be lost!
index 878b2ce06a9a74dec2ea2439ff90029e6f7f4c21..dd17e87f48f21ef0901632ec7f8ae3d85906bc66 100644 (file)
@@ -82,30 +82,29 @@ using _gpgme_::KDPipeIODevice;
    really nice callback interfaces to let the user control all this at
    a per-context level.  */
 
-#define MAX_SLAFD 50000
+#define MAX_SLAFD 1024
 
 struct DeviceEntry {
-  DeviceEntry() : iodev( 0 ), actual_fd( -1 ), refCount( 1 ) {}
-    QIODevice* iodev;
-    int actual_fd;
+  DeviceEntry() : iodev( 0 ), refCount( 1 ) {}
+    KDPipeIODevice* iodev;
     mutable int refCount;
     void ref() const { ++refCount; }
-    int unref() const { return --refCount; }
+    int unref() const { assert( refCount > 0 ); return --refCount; }
 };
 
 DeviceEntry* iodevice_table[MAX_SLAFD];
 
 
-static QIODevice *
+static KDPipeIODevice *
 find_channel (int fd, int create)
 {
+  assert( fd < MAX_SLAFD );
   if (fd < 0 || fd >= MAX_SLAFD)
     return NULL;
 
   if (create && !iodevice_table[fd])
   {
     DeviceEntry* entry = new DeviceEntry;
-    entry->actual_fd = fd;
     entry->iodev = new KDPipeIODevice
       (fd, QIODevice::ReadWrite|QIODevice::Unbuffered);
     iodevice_table[fd] = entry; 
@@ -117,11 +116,9 @@ find_channel (int fd, int create)
    BUFLEN.  The printable version is the representation on the command
    line that the child process expects.  */
 int
-_gpgme_io_fd2str (char *buf, int buflen, int fd_)
+_gpgme_io_fd2str (char *buf, int buflen, int fd)
 {
-  const int actual_fd = iodevice_table[fd_] ? iodevice_table[fd_]->actual_fd : fd_;
-  return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (actual_fd));
-  //  return snprintf (buf, buflen, "%d", fd);
+  return snprintf (buf, buflen, "%d", (long)_get_osfhandle( fd ) );
 }
 
 \f
@@ -143,7 +140,7 @@ _gpgme_io_read (int fd, void *buffer, size_t count)
 {
   int saved_errno = 0;
   qint64 nread;
-  QIODevice *chan;
+  KDPipeIODevice *chan;
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
              "buffer=%p, count=%u", buffer, count);
 
@@ -175,7 +172,7 @@ int
 _gpgme_io_write (int fd, const void *buffer, size_t count)
 {
   qint64 nwritten;
-  QIODevice *chan;
+  KDPipeIODevice *chan;
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
              "buffer=%p, count=%u", buffer, count);
   TRACE_LOGBUF ((char *) buffer, count);
@@ -204,7 +201,7 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
 int
 _gpgme_io_pipe (int filedes[2], int inherit_idx)
 {
-  QIODevice *chan;
+  KDPipeIODevice *chan;
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
              "inherit_idx=%i (GPGME uses it for %s)",
              inherit_idx, inherit_idx ? "reading" : "writing");
@@ -266,7 +263,7 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
 int
 _gpgme_io_close (int fd)
 {
-  QIODevice *chan;
+  KDPipeIODevice *chan;
   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
 
   if (fd < 0 || fd >= MAX_SLAFD)
@@ -286,27 +283,19 @@ _gpgme_io_close (int fd)
   /* Then do the close.  */    
   
   DeviceEntry* const entry = iodevice_table[fd];
-  if ( entry )
-  {
-    assert( entry->refCount > 0 );
-    const int actual_fd = entry->actual_fd;
-    assert( actual_fd > 0 );
-    if ( !entry->unref() ) {
-      entry->iodev->close();
-      delete entry->iodev;
-      delete entry;
-      for ( int i = 0; i < MAX_SLAFD; ++i ) {
-        if ( iodevice_table[i] == entry )
-          iodevice_table[i] = 0;      
+  if ( entry ) {
+      if ( entry->unref() == 0 ) {
+          entry->iodev->close();
+          delete entry->iodev;
+          delete entry;
+          iodevice_table[fd] = 0;
       }
-    }
-
-    if ( fd != actual_fd )
-      _close( fd );       
+  } else {
+      _close( fd );
   }
-  else
-    _close (fd);
+
   
+
   return 0;
 }
 
@@ -337,7 +326,6 @@ _gpgme_io_set_nonblocking (int fd)
   /* Qt always uses non-blocking IO, except for files, maybe, but who
      uses that?  */
   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
-
   return TRACE_SYSRES (0);
 }
 
@@ -538,6 +526,7 @@ _gpgme_io_spawn (const char *path, char **argv,
   /* Close the other ends of the pipes.  */
   for (i = 0; fd_parent_list[i].fd != -1; i++)
     _gpgme_io_close (fd_parent_list[i].fd);
+
   
   TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
              "dwProcessID=%d, dwThreadId=%d",
@@ -565,8 +554,6 @@ _gpgme_io_spawn (const char *path, char **argv,
 int
 _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
 {
-  int i;
-  int count;
   /* Use a 1s timeout.  */
 
   void *dbg_help = NULL;
@@ -576,30 +563,32 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
   /* We only implement the special case of nonblock == true.  */
   assert (nonblock);
 
-  count = 0;
+  int count = 0;
 
   TRACE_SEQ (dbg_help, "select on [ ");
-  for (i = 0; i < nfds; i++)
+  for (int i = 0; i < nfds; i++)
     {
       if (fds[i].fd == -1)
         {
           fds[i].signaled = 0;
-        }
-      else if (fds[i].for_read)
-        {
-          const QIODevice * const chan = find_channel (fds[i].fd, 0);
-          assert (chan);
-          fds[i].signaled = chan->bytesAvailable() > 0 ? 1 : 0 ;
-          TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
-          count++;
+       }
+      else if (fds[i].for_read )
+      {
+          const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0);
+          assert (chan);   
+          fds[i].signaled = chan->readWouldBlock() ? 0 : 1;
+         TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
+          if ( fds[i].signaled ) 
+              count++;
         }
       else if (fds[i].for_write)
         {
-          const QIODevice * const chan = find_channel (fds[i].fd, 0);
+          const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0);
           assert (chan);
-          fds[i].signaled = chan->bytesToWrite() > 0 ? 0 : 1 ;
+          fds[i].signaled = chan->writeWouldBlock() ? 0 : 1;
           TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
-          count++;
+          if ( fds[i].signaled ) 
+              count++;
         }
     }
   TRACE_END (dbg_help, "]"); 
@@ -629,21 +618,8 @@ gpgme_get_giochannel (int fd)
 int
 _gpgme_io_dup (int fd)
 {
-    DeviceEntry* const existing = iodevice_table[fd];
-    if ( existing )
-        existing->ref();
-    else
-        find_channel( fd, /*create=*/1 );
+    assert( iodevice_table[fd] );
+    iodevice_table[fd]->ref();
     return fd;
-#if 0
-  const int new_fd = _dup( fd );
-  iodevice_table[new_fd] = iodevice_table[fd];
-  if ( iodevice_table[new_fd] )
-    iodevice_table[new_fd]->ref();
-  else
-    find_channel( new_fd, /*create=*/1 ); 
-  return new_fd;
-#endif
 }