2007-09-28 Marcus Brinkmann <marcus@g10code.de>
* kdpipeiodevice.moc, w32-qt-io.cpp, kdpipeiodevice.cpp: New versions from Frank Osterfeld.
This commit is contained in:
parent
37ac53e74c
commit
7e82572bb2
@ -1,3 +1,8 @@
|
|||||||
|
2007-09-28 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* kdpipeiodevice.moc, w32-qt-io.cpp, kdpipeiodevice.cpp: New
|
||||||
|
versions from Frank Osterfeld.
|
||||||
|
|
||||||
2007-09-27 Marcus Brinkmann <marcus@g10code.de>
|
2007-09-27 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* w32-glib-io.c (_gpgme_io_spawn),
|
* w32-glib-io.c (_gpgme_io_spawn),
|
||||||
|
@ -51,7 +51,7 @@ const unsigned int BUFFER_SIZE = 4096;
|
|||||||
const bool ALLOW_QIODEVICE_BUFFERING = true;
|
const bool ALLOW_QIODEVICE_BUFFERING = true;
|
||||||
|
|
||||||
// comment to get trace output:
|
// comment to get trace output:
|
||||||
#define qDebug if(1){}else qDebug
|
//#define qDebug if(1){}else qDebug
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class Reader : public QThread {
|
class Reader : public QThread {
|
||||||
@ -188,7 +188,8 @@ Writer::Writer( int fd_, Qt::HANDLE handle_ )
|
|||||||
Writer::~Writer() {}
|
Writer::~Writer() {}
|
||||||
|
|
||||||
|
|
||||||
class KDPipeIODevice::Private {
|
class KDPipeIODevice::Private : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
friend class ::KDPipeIODevice;
|
friend class ::KDPipeIODevice;
|
||||||
KDPipeIODevice * const q;
|
KDPipeIODevice * const q;
|
||||||
public:
|
public:
|
||||||
@ -196,6 +197,11 @@ public:
|
|||||||
~Private();
|
~Private();
|
||||||
|
|
||||||
bool doOpen( int, Qt::HANDLE, OpenMode );
|
bool doOpen( int, Qt::HANDLE, OpenMode );
|
||||||
|
bool startReaderThread();
|
||||||
|
bool startWriterThread();
|
||||||
|
void stopThreads();
|
||||||
|
bool triedToStartReader;
|
||||||
|
bool triedToStartWriter;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fd;
|
int fd;
|
||||||
@ -205,19 +211,18 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
KDPipeIODevice::Private::Private( KDPipeIODevice * qq )
|
KDPipeIODevice::Private::Private( KDPipeIODevice * qq )
|
||||||
: q( qq ),
|
: QObject( qq ), q( qq ),
|
||||||
fd( -1 ),
|
fd( -1 ),
|
||||||
handle( 0 ),
|
handle( 0 ),
|
||||||
reader( 0 ),
|
reader( 0 ),
|
||||||
writer( 0 )
|
writer( 0 ),
|
||||||
|
triedToStartReader( false ), triedToStartWriter( false )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KDPipeIODevice::Private::~Private() {}
|
KDPipeIODevice::Private::~Private() {}
|
||||||
|
|
||||||
|
|
||||||
KDPipeIODevice::KDPipeIODevice( QObject * p )
|
KDPipeIODevice::KDPipeIODevice( QObject * p )
|
||||||
: QIODevice( p ), d( new Private( this ) )
|
: QIODevice( p ), d( new Private( this ) )
|
||||||
{
|
{
|
||||||
@ -267,6 +272,36 @@ bool KDPipeIODevice::open( Qt::HANDLE h, OpenMode mode ) { KDAB_CHECK_THIS;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::Private::startReaderThread()
|
||||||
|
{
|
||||||
|
if ( triedToStartReader )
|
||||||
|
return true;
|
||||||
|
triedToStartReader = true;
|
||||||
|
if ( reader && !reader->isRunning() && !reader->isFinished() ) {
|
||||||
|
LOCKED( reader );
|
||||||
|
|
||||||
|
reader->start( QThread::HighestPriority );
|
||||||
|
if ( !reader->hasStarted.wait( &reader->mutex, 1000 ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::Private::startWriterThread()
|
||||||
|
{
|
||||||
|
if ( triedToStartWriter )
|
||||||
|
return true;
|
||||||
|
triedToStartWriter = true;
|
||||||
|
if ( writer && !writer->isRunning() && !writer->isFinished() ) {
|
||||||
|
LOCKED( writer );
|
||||||
|
|
||||||
|
writer->start( QThread::HighestPriority );
|
||||||
|
if ( !writer->hasStarted.wait( &writer->mutex, 1000 ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) {
|
bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) {
|
||||||
|
|
||||||
if ( q->isOpen() || fd_ < 0 )
|
if ( q->isOpen() || fd_ < 0 )
|
||||||
@ -288,19 +323,15 @@ bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode
|
|||||||
|
|
||||||
if ( mode_ & ReadOnly ) {
|
if ( mode_ & ReadOnly ) {
|
||||||
reader_.reset( new Reader( fd_, handle_ ) );
|
reader_.reset( new Reader( fd_, handle_ ) );
|
||||||
LOCKED( reader_ );
|
qDebug( "KDPipeIODevice::doOpen: created reader for fd %d", fd_ );
|
||||||
reader_->start( QThread::HighestPriority );
|
connect( reader_.get(), SIGNAL(readyRead()), q,
|
||||||
if ( !reader_->hasStarted.wait( &reader_->mutex, 1000 ) )
|
SIGNAL(readyRead()), Qt::QueuedConnection );
|
||||||
return false;
|
|
||||||
connect( reader_.get(), SIGNAL(readyRead()), q, SIGNAL(readyRead()), Qt::QueuedConnection );
|
|
||||||
}
|
}
|
||||||
if ( mode_ & WriteOnly ) {
|
if ( mode_ & WriteOnly ) {
|
||||||
writer_.reset( new Writer( fd_, handle_ ) );
|
writer_.reset( new Writer( fd_, handle_ ) );
|
||||||
LOCKED( writer_ );
|
qDebug( "KDPipeIODevice::doOpen: created writer for fd %d", fd_ );
|
||||||
writer_->start( QThread::HighestPriority );
|
connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)),
|
||||||
if ( !writer_->hasStarted.wait( &writer_->mutex, 1000 ) )
|
Qt::QueuedConnection );
|
||||||
return false;
|
|
||||||
connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit to *this:
|
// commit to *this:
|
||||||
@ -310,7 +341,6 @@ bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode
|
|||||||
writer = writer_.release();
|
writer = writer_.release();
|
||||||
|
|
||||||
q->setOpenMode( mode_|Unbuffered );
|
q->setOpenMode( mode_|Unbuffered );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,18 +348,24 @@ int KDPipeIODevice::descriptor() const { KDAB_CHECK_THIS;
|
|||||||
return d->fd;
|
return d->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS;
|
Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS;
|
||||||
return d->handle;
|
return d->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS;
|
qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS;
|
||||||
const qint64 base = QIODevice::bytesAvailable();
|
const qint64 base = QIODevice::bytesAvailable();
|
||||||
|
if ( !d->triedToStartReader ) {
|
||||||
|
d->startReaderThread();
|
||||||
|
return base;
|
||||||
|
}
|
||||||
if ( d->reader )
|
if ( d->reader )
|
||||||
synchronized( d->reader ) return base + d->reader->bytesInBuffer();
|
synchronized( d->reader ) return base + d->reader->bytesInBuffer();
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS;
|
qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS;
|
||||||
|
d->startWriterThread();
|
||||||
const qint64 base = QIODevice::bytesToWrite();
|
const qint64 base = QIODevice::bytesToWrite();
|
||||||
if ( d->writer )
|
if ( d->writer )
|
||||||
synchronized( d->writer ) return base + d->writer->bytesInBuffer();
|
synchronized( d->writer ) return base + d->writer->bytesInBuffer();
|
||||||
@ -337,6 +373,7 @@ qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS;
|
bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS;
|
||||||
|
d->startReaderThread();
|
||||||
if ( QIODevice::canReadLine() )
|
if ( QIODevice::canReadLine() )
|
||||||
return true;
|
return true;
|
||||||
if ( d->reader )
|
if ( d->reader )
|
||||||
@ -349,8 +386,9 @@ bool KDPipeIODevice::isSequential() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS;
|
bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS;
|
||||||
|
d->startReaderThread();
|
||||||
if ( !QIODevice::atEnd() ) {
|
if ( !QIODevice::atEnd() ) {
|
||||||
qDebug( "KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", static_cast<long>(bytesAvailable()) );
|
qDebug( "%p: KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", this, static_cast<long>(bytesAvailable()) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( !isOpen() )
|
if ( !isOpen() )
|
||||||
@ -361,14 +399,15 @@ bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS;
|
|||||||
const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty();
|
const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty();
|
||||||
if ( !eof ) {
|
if ( !eof ) {
|
||||||
if ( !d->reader->error && !d->reader->eof )
|
if ( !d->reader->error && !d->reader->eof )
|
||||||
qDebug( "KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof" );
|
qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof", this );
|
||||||
if ( !d->reader->bufferEmpty() )
|
if ( !d->reader->bufferEmpty() )
|
||||||
qDebug( "KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()" );
|
qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()", this );
|
||||||
}
|
}
|
||||||
return eof;
|
return eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS;
|
bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS;
|
||||||
|
d->startWriterThread();
|
||||||
Writer * const w = d->writer;
|
Writer * const w = d->writer;
|
||||||
if ( !w )
|
if ( !w )
|
||||||
return true;
|
return true;
|
||||||
@ -377,6 +416,7 @@ bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
|
bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
|
||||||
|
d->startReaderThread();
|
||||||
if ( ALLOW_QIODEVICE_BUFFERING ) {
|
if ( ALLOW_QIODEVICE_BUFFERING ) {
|
||||||
if ( bytesAvailable() > 0 )
|
if ( bytesAvailable() > 0 )
|
||||||
return true;
|
return true;
|
||||||
@ -389,18 +429,22 @@ bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS;
|
qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS;
|
||||||
|
qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, data, maxSize );
|
||||||
|
|
||||||
qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld", data, maxSize );
|
if ( maxSize == 0 )
|
||||||
|
return 0;
|
||||||
|
d->startReaderThread();
|
||||||
|
|
||||||
Reader * const r = d->reader;
|
Reader * const r = d->reader;
|
||||||
|
|
||||||
assert( r );
|
assert( r );
|
||||||
|
|
||||||
//assert( r->isRunning() ); // wrong (might be eof, error)
|
//assert( r->isRunning() ); // wrong (might be eof, error)
|
||||||
assert( data || maxSize == 0 );
|
assert( data || maxSize == 0 );
|
||||||
assert( maxSize >= 0 );
|
assert( maxSize >= 0 );
|
||||||
|
|
||||||
if ( r->eofShortCut ) {
|
if ( r->eofShortCut ) {
|
||||||
qDebug( "KDPipeIODevice::readData: hit eofShortCut, returning 0" );
|
qDebug( "%p: KDPipeIODevice::readData: hit eofShortCut, returning 0", this );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,31 +458,31 @@ qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS
|
|||||||
|
|
||||||
LOCKED( r );
|
LOCKED( r );
|
||||||
if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0?
|
if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0?
|
||||||
qDebug( "KDPipeIODevice::readData: waiting for bufferNotEmptyCondition" );
|
qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition", this );
|
||||||
r->bufferNotEmptyCondition.wait( &r->mutex );
|
r->bufferNotEmptyCondition.wait( &r->mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( r->bufferEmpty() ) {
|
if ( r->bufferEmpty() ) {
|
||||||
qDebug( "KDPipeIODevice::readData: got empty buffer, signal eof" );
|
qDebug( "%p: KDPipeIODevice::readData: got empty buffer, signal eof", this );
|
||||||
// woken with an empty buffer must mean either EOF or error:
|
// woken with an empty buffer must mean either EOF or error:
|
||||||
assert( r->eof || r->error );
|
assert( r->eof || r->error );
|
||||||
r->eofShortCut = true;
|
r->eofShortCut = true;
|
||||||
return r->eof ? 0 : -1 ;
|
return r->eof ? 0 : -1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug( "KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", maxSize );
|
qDebug( "%p: KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", this, maxSize );
|
||||||
const qint64 bytesRead = r->readData( data, maxSize );
|
const qint64 bytesRead = r->readData( data, maxSize );
|
||||||
qDebug( "KDPipeIODevice::readData: read %lld bytes", bytesRead );
|
qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead );
|
||||||
|
qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data );
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 Reader::readData( char * data, qint64 maxSize ) {
|
qint64 Reader::readData( char * data, qint64 maxSize ) {
|
||||||
|
|
||||||
qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ;
|
qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ;
|
||||||
if ( numRead > maxSize )
|
if ( numRead > maxSize )
|
||||||
numRead = maxSize;
|
numRead = maxSize;
|
||||||
|
|
||||||
qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld",
|
qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld", this,
|
||||||
data, maxSize, rptr, wptr, bytesInBuffer(), numRead );
|
data, maxSize, rptr, wptr, bytesInBuffer(), numRead );
|
||||||
|
|
||||||
std::memcpy( data, buffer + rptr, numRead );
|
std::memcpy( data, buffer + rptr, numRead );
|
||||||
@ -446,7 +490,7 @@ qint64 Reader::readData( char * data, qint64 maxSize ) {
|
|||||||
rptr = ( rptr + numRead ) % sizeof buffer ;
|
rptr = ( rptr + numRead ) % sizeof buffer ;
|
||||||
|
|
||||||
if ( !bufferFull() ) {
|
if ( !bufferFull() ) {
|
||||||
qDebug( "KDPipeIODevice::readData: signal bufferNotFullCondition" );
|
qDebug( "%p: KDPipeIODevice::readData: signal bufferNotFullCondition", this );
|
||||||
bufferNotFullCondition.wakeAll();
|
bufferNotFullCondition.wakeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +498,7 @@ qint64 Reader::readData( char * data, qint64 maxSize ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS;
|
qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS;
|
||||||
|
d->startWriterThread();
|
||||||
Writer * const w = d->writer;
|
Writer * const w = d->writer;
|
||||||
|
|
||||||
assert( w );
|
assert( w );
|
||||||
@ -476,7 +520,6 @@ qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_
|
|||||||
}
|
}
|
||||||
|
|
||||||
qint64 Writer::writeData( const char * data, qint64 size ) {
|
qint64 Writer::writeData( const char * data, qint64 size ) {
|
||||||
|
|
||||||
assert( bufferEmpty() );
|
assert( bufferEmpty() );
|
||||||
|
|
||||||
if ( size > static_cast<qint64>( sizeof buffer ) )
|
if ( size > static_cast<qint64>( sizeof buffer ) )
|
||||||
@ -492,6 +535,33 @@ qint64 Writer::writeData( const char * data, qint64 size ) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KDPipeIODevice::Private::stopThreads()
|
||||||
|
{
|
||||||
|
if ( triedToStartWriter )
|
||||||
|
{
|
||||||
|
if ( writer && q->bytesToWrite() > 0 )
|
||||||
|
q->waitForBytesWritten( -1 );
|
||||||
|
|
||||||
|
assert( q->bytesToWrite() == 0 );
|
||||||
|
}
|
||||||
|
if ( Reader * & r = reader ) {
|
||||||
|
synchronized( r ) {
|
||||||
|
// tell thread to cancel:
|
||||||
|
r->cancel = true;
|
||||||
|
// and wake it, so it can terminate:
|
||||||
|
r->bufferNotFullCondition.wakeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( Writer * & w = writer ) {
|
||||||
|
synchronized( w ) {
|
||||||
|
// tell thread to cancel:
|
||||||
|
w->cancel = true;
|
||||||
|
// and wake it, so it can terminate:
|
||||||
|
w->bufferNotEmptyCondition.wakeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KDPipeIODevice::close() { KDAB_CHECK_THIS;
|
void KDPipeIODevice::close() { KDAB_CHECK_THIS;
|
||||||
|
|
||||||
if ( !isOpen() )
|
if ( !isOpen() )
|
||||||
@ -499,32 +569,12 @@ void KDPipeIODevice::close() { KDAB_CHECK_THIS;
|
|||||||
|
|
||||||
// tell clients we're about to close:
|
// tell clients we're about to close:
|
||||||
emit aboutToClose();
|
emit aboutToClose();
|
||||||
|
d->stopThreads();
|
||||||
|
|
||||||
if ( d->writer && bytesToWrite() > 0 )
|
#define waitAndDelete( t ) if ( t ) { t->wait(); delete t; t = 0; }
|
||||||
waitForBytesWritten( -1 );
|
waitAndDelete( d->writer );
|
||||||
|
waitAndDelete( d->reader );
|
||||||
assert( bytesToWrite() == 0 );
|
#undef waitAndDelete
|
||||||
|
|
||||||
if ( Reader * & r = d->reader ) {
|
|
||||||
synchronized( r ) {
|
|
||||||
// tell thread to cancel:
|
|
||||||
r->cancel = true;
|
|
||||||
// and wake it, so it can terminate:
|
|
||||||
r->bufferNotFullCondition.wakeAll();
|
|
||||||
}
|
|
||||||
r->wait();
|
|
||||||
delete r; r = 0;
|
|
||||||
}
|
|
||||||
if ( Writer * & w = d->writer ) {
|
|
||||||
synchronized( w ) {
|
|
||||||
// tell thread to cancel:
|
|
||||||
w->cancel = true;
|
|
||||||
// and wake it, so it can terminate:
|
|
||||||
w->bufferNotEmptyCondition.wakeAll();
|
|
||||||
}
|
|
||||||
w->wait();
|
|
||||||
delete w; w = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
CloseHandle( d->handle );
|
CloseHandle( d->handle );
|
||||||
@ -544,19 +594,19 @@ void Reader::run() {
|
|||||||
// too bad QThread doesn't have that itself; a signal isn't enough
|
// too bad QThread doesn't have that itself; a signal isn't enough
|
||||||
hasStarted.wakeAll();
|
hasStarted.wakeAll();
|
||||||
|
|
||||||
qDebug( "Reader::run: started" );
|
qDebug( "%p: Reader::run: started", this );
|
||||||
|
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
|
|
||||||
while ( !cancel && bufferFull() ) {
|
while ( !cancel && bufferFull() ) {
|
||||||
bufferNotEmptyCondition.wakeAll();
|
bufferNotEmptyCondition.wakeAll();
|
||||||
qDebug( "Reader::run: buffer is full, going to sleep" );
|
qDebug( "%p: Reader::run: buffer is full, going to sleep", this );
|
||||||
bufferNotFullCondition.wait( &mutex );
|
bufferNotFullCondition.wait( &mutex );
|
||||||
qDebug( "Reader::run: woke up" );
|
qDebug( "%p: Reader::run: woke up", this );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cancel ) {
|
if ( cancel ) {
|
||||||
qDebug( "Reader::run: detected cancel" );
|
qDebug( "%p: Reader::run: detected cancel", this );
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,11 +617,11 @@ void Reader::run() {
|
|||||||
if ( numBytes > sizeof buffer - wptr )
|
if ( numBytes > sizeof buffer - wptr )
|
||||||
numBytes = sizeof buffer - wptr;
|
numBytes = sizeof buffer - wptr;
|
||||||
|
|
||||||
qDebug( "Reader::run: rptr=%d, wptr=%d -> numBytes=%d", rptr, wptr, numBytes );
|
qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes );
|
||||||
|
|
||||||
assert( numBytes > 0 );
|
assert( numBytes > 0 );
|
||||||
|
|
||||||
qDebug( "Reader::run: trying to read %d bytes", numBytes );
|
qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes );
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
DWORD numRead;
|
DWORD numRead;
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
@ -580,10 +630,10 @@ void Reader::run() {
|
|||||||
if ( !ok ) {
|
if ( !ok ) {
|
||||||
errorCode = static_cast<int>( GetLastError() );
|
errorCode = static_cast<int>( GetLastError() );
|
||||||
if ( errorCode == ERROR_BROKEN_PIPE ) {
|
if ( errorCode == ERROR_BROKEN_PIPE ) {
|
||||||
qDebug( "Reader::run: got eof" );
|
qDebug( "%p: Reader::run: got eof (broken pipe)", this );
|
||||||
eof = true;
|
eof = true;
|
||||||
} else {
|
} else {
|
||||||
qDebug( "Reader::run: got error: %d", errorCode );
|
qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode );
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -599,32 +649,33 @@ void Reader::run() {
|
|||||||
if ( numRead < 0 ) {
|
if ( numRead < 0 ) {
|
||||||
errorCode = errno;
|
errorCode = errno;
|
||||||
error = true;
|
error = true;
|
||||||
qDebug( "Reader::run: got error: %d", errorCode );
|
qDebug( "%p: Reader::run: got error: %d", this, errorCode );
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
qDebug( "Reader::run: read %ld bytes", static_cast<long>(numRead) );
|
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 ) {
|
if ( numRead == 0 ) {
|
||||||
qDebug( "Reader::run: eof detected" );
|
qDebug( "%p: Reader::run: eof detected", this );
|
||||||
eof = true;
|
eof = true;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cancel ) {
|
if ( cancel ) {
|
||||||
qDebug( "Reader::run: detected cancel" );
|
qDebug( "%p: Reader::run: detected cancel", this );
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
qDebug( "Reader::run: buffer before: rptr=%4d, wptr=%4d", rptr, wptr );
|
qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr );
|
||||||
wptr = ( wptr + numRead ) % sizeof buffer;
|
wptr = ( wptr + numRead ) % sizeof buffer;
|
||||||
qDebug( "Reader::run: buffer after: rptr=%4d, wptr=%4d", rptr, wptr );
|
qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr );
|
||||||
if ( !bufferEmpty() ) {
|
if ( !bufferEmpty() ) {
|
||||||
qDebug( "Reader::run: buffer no longer empty, waking everyone" );
|
qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this );
|
||||||
bufferNotEmptyCondition.wakeAll();
|
bufferNotEmptyCondition.wakeAll();
|
||||||
emit readyRead();
|
emit readyRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
leave:
|
leave:
|
||||||
qDebug( "Reader::run: terminating" );
|
qDebug( "%p: Reader::run: terminating", this );
|
||||||
bufferNotEmptyCondition.wakeAll();
|
bufferNotEmptyCondition.wakeAll();
|
||||||
emit readyRead();
|
emit readyRead();
|
||||||
}
|
}
|
||||||
@ -636,25 +687,25 @@ void Writer::run() {
|
|||||||
// too bad QThread doesn't have that itself; a signal isn't enough
|
// too bad QThread doesn't have that itself; a signal isn't enough
|
||||||
hasStarted.wakeAll();
|
hasStarted.wakeAll();
|
||||||
|
|
||||||
qDebug( "Writer::run: started" );
|
qDebug( "%p: Writer::run: started", this );
|
||||||
|
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
|
|
||||||
while ( !cancel && bufferEmpty() ) {
|
while ( !cancel && bufferEmpty() ) {
|
||||||
bufferEmptyCondition.wakeAll();
|
bufferEmptyCondition.wakeAll();
|
||||||
qDebug( "Writer::run: buffer is empty, going to sleep" );
|
qDebug( "%p: Writer::run: buffer is empty, going to sleep", this );
|
||||||
bufferNotEmptyCondition.wait( &mutex );
|
bufferNotEmptyCondition.wait( &mutex );
|
||||||
qDebug( "Writer::run: woke up" );
|
qDebug( "%p: Writer::run: woke up", this );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cancel ) {
|
if ( cancel ) {
|
||||||
qDebug( "Writer::run: detected cancel" );
|
qDebug( "%p: Writer::run: detected cancel", this );
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( numBytesInBuffer > 0 );
|
assert( numBytesInBuffer > 0 );
|
||||||
|
|
||||||
qDebug( "Writer::run: Trying to write %u bytes", numBytesInBuffer );
|
qDebug( "%p: Writer::run: Trying to write %u bytes", this, numBytesInBuffer );
|
||||||
qint64 totalWritten = 0;
|
qint64 totalWritten = 0;
|
||||||
do {
|
do {
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
@ -663,7 +714,7 @@ void Writer::run() {
|
|||||||
if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) {
|
if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
errorCode = static_cast<int>( GetLastError() );
|
errorCode = static_cast<int>( GetLastError() );
|
||||||
qDebug( "Writer::run: got error code: %d", errorCode );
|
qDebug( "%p: Writer::run: got error code: %d", this, errorCode );
|
||||||
error = true;
|
error = true;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -676,7 +727,7 @@ void Writer::run() {
|
|||||||
if ( numWritten < 0 ) {
|
if ( numWritten < 0 ) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
errorCode = errno;
|
errorCode = errno;
|
||||||
qDebug( "Writer::run: got error code: %d", errorCode );
|
qDebug( "%p: Writer::run: got error code: %d", this, errorCode );
|
||||||
error = true;
|
error = true;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -685,14 +736,14 @@ void Writer::run() {
|
|||||||
mutex.lock();
|
mutex.lock();
|
||||||
} while ( totalWritten < numBytesInBuffer );
|
} while ( totalWritten < numBytesInBuffer );
|
||||||
|
|
||||||
qDebug( "Writer::run: wrote %lld bytes", totalWritten );
|
qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten );
|
||||||
|
|
||||||
numBytesInBuffer = 0;
|
numBytesInBuffer = 0;
|
||||||
bufferEmptyCondition.wakeAll();
|
bufferEmptyCondition.wakeAll();
|
||||||
emit bytesWritten( totalWritten );
|
emit bytesWritten( totalWritten );
|
||||||
}
|
}
|
||||||
leave:
|
leave:
|
||||||
qDebug( "Writer::run: terminating" );
|
qDebug( "%p: Writer::run: terminating", this );
|
||||||
numBytesInBuffer = 0;
|
numBytesInBuffer = 0;
|
||||||
bufferEmptyCondition.wakeAll();
|
bufferEmptyCondition.wakeAll();
|
||||||
emit bytesWritten( 0 );
|
emit bytesWritten( 0 );
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'kdpipeiodevice.cpp'
|
** Meta object code from reading C++ file 'kdpipeiodevice.cpp'
|
||||||
**
|
**
|
||||||
** Created: Mon Aug 27 15:17:18 2007
|
** Created: Wed Sep 26 11:05:05 2007
|
||||||
** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0)
|
** by: The Qt Meta Object Compiler version 59 (Qt 4.3.1)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@ -10,7 +10,7 @@
|
|||||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||||
#error "The header file 'kdpipeiodevice.cpp' doesn't include <QObject>."
|
#error "The header file 'kdpipeiodevice.cpp' doesn't include <QObject>."
|
||||||
#elif Q_MOC_OUTPUT_REVISION != 59
|
#elif Q_MOC_OUTPUT_REVISION != 59
|
||||||
#error "This file was generated using the moc from 4.3.0. It"
|
#error "This file was generated using the moc from 4.3.1. It"
|
||||||
#error "cannot be used with the include files from this version of Qt."
|
#error "cannot be used with the include files from this version of Qt."
|
||||||
#error "(The moc has changed too much.)"
|
#error "(The moc has changed too much.)"
|
||||||
#endif
|
#endif
|
||||||
@ -130,3 +130,45 @@ void Writer::bytesWritten(qint64 _t1)
|
|||||||
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||||
}
|
}
|
||||||
|
static const uint qt_meta_data_KDPipeIODevice__Private[] = {
|
||||||
|
|
||||||
|
// content:
|
||||||
|
1, // revision
|
||||||
|
0, // classname
|
||||||
|
0, 0, // classinfo
|
||||||
|
0, 0, // methods
|
||||||
|
0, 0, // properties
|
||||||
|
0, 0, // enums/sets
|
||||||
|
|
||||||
|
0 // eod
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char qt_meta_stringdata_KDPipeIODevice__Private[] = {
|
||||||
|
"KDPipeIODevice::Private\0"
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject KDPipeIODevice::Private::staticMetaObject = {
|
||||||
|
{ &QObject::staticMetaObject, qt_meta_stringdata_KDPipeIODevice__Private,
|
||||||
|
qt_meta_data_KDPipeIODevice__Private, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject *KDPipeIODevice::Private::metaObject() const
|
||||||
|
{
|
||||||
|
return &staticMetaObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *KDPipeIODevice::Private::qt_metacast(const char *_clname)
|
||||||
|
{
|
||||||
|
if (!_clname) return 0;
|
||||||
|
if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice__Private))
|
||||||
|
return static_cast<void*>(const_cast< Private*>(this));
|
||||||
|
return QObject::qt_metacast(_clname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int KDPipeIODevice::Private::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||||
|
{
|
||||||
|
_id = QObject::qt_metacall(_c, _id, _a);
|
||||||
|
if (_id < 0)
|
||||||
|
return _id;
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
@ -82,10 +82,18 @@ using _gpgme_::KDPipeIODevice;
|
|||||||
really nice callback interfaces to let the user control all this at
|
really nice callback interfaces to let the user control all this at
|
||||||
a per-context level. */
|
a per-context level. */
|
||||||
|
|
||||||
|
#define MAX_SLAFD 50000
|
||||||
#define MAX_SLAFD 256
|
|
||||||
|
|
||||||
QIODevice *iodevice_table[MAX_SLAFD];
|
struct DeviceEntry {
|
||||||
|
DeviceEntry() : iodev( 0 ), actual_fd( -1 ), refCount( 1 ) {}
|
||||||
|
QIODevice* iodev;
|
||||||
|
int actual_fd;
|
||||||
|
mutable int refCount;
|
||||||
|
void ref() const { ++refCount; }
|
||||||
|
int unref() const { return --refCount; }
|
||||||
|
};
|
||||||
|
|
||||||
|
DeviceEntry* iodevice_table[MAX_SLAFD];
|
||||||
|
|
||||||
|
|
||||||
static QIODevice *
|
static QIODevice *
|
||||||
@ -95,13 +103,16 @@ find_channel (int fd, int create)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (create && !iodevice_table[fd])
|
if (create && !iodevice_table[fd])
|
||||||
iodevice_table[fd] = new KDPipeIODevice
|
{
|
||||||
(fd, QIODevice::ReadOnly|QIODevice::Unbuffered);
|
DeviceEntry* entry = new DeviceEntry;
|
||||||
|
entry->actual_fd = fd;
|
||||||
return iodevice_table[fd];
|
entry->iodev = new KDPipeIODevice
|
||||||
|
(fd, QIODevice::ReadWrite|QIODevice::Unbuffered);
|
||||||
|
iodevice_table[fd] = entry;
|
||||||
|
}
|
||||||
|
return iodevice_table[fd] ? iodevice_table[fd]->iodev : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write the printable version of FD to the buffer BUF of length
|
/* Write the printable version of FD to the buffer BUF of length
|
||||||
BUFLEN. The printable version is the representation on the command
|
BUFLEN. The printable version is the representation on the command
|
||||||
line that the child process expects. */
|
line that the child process expects. */
|
||||||
@ -232,7 +243,9 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
|
|||||||
|
|
||||||
/* Now we have a pipe with the right end inheritable. The other end
|
/* Now we have a pipe with the right end inheritable. The other end
|
||||||
should have a giochannel. */
|
should have a giochannel. */
|
||||||
|
|
||||||
chan = find_channel (filedes[1 - inherit_idx], 1);
|
chan = find_channel (filedes[1 - inherit_idx], 1);
|
||||||
|
|
||||||
if (!chan)
|
if (!chan)
|
||||||
{
|
{
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
@ -248,7 +261,6 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
|
|||||||
chan);
|
chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_gpgme_io_close (int fd)
|
_gpgme_io_close (int fd)
|
||||||
{
|
{
|
||||||
@ -270,12 +282,25 @@ _gpgme_io_close (int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Then do the close. */
|
/* Then do the close. */
|
||||||
chan = iodevice_table[fd];
|
|
||||||
if (chan)
|
DeviceEntry* const entry = iodevice_table[fd];
|
||||||
|
if ( entry )
|
||||||
{
|
{
|
||||||
chan->close();
|
assert( entry->refCount > 0 );
|
||||||
delete chan;
|
const int actual_fd = entry->actual_fd;
|
||||||
iodevice_table[fd] = NULL;
|
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 ( fd != actual_fd )
|
||||||
|
_close( fd );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_close (fd);
|
_close (fd);
|
||||||
@ -586,13 +611,6 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_gpgme_io_dup (int fd)
|
|
||||||
{
|
|
||||||
return _dup (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Look up the qiodevice for file descriptor FD. */
|
/* Look up the qiodevice for file descriptor FD. */
|
||||||
extern "C"
|
extern "C"
|
||||||
void *
|
void *
|
||||||
@ -610,3 +628,16 @@ gpgme_get_giochannel (int fd)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_dup (int fd)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user