[Pkg-owncloud-commits] [qtkeychain] 41/115: D-Bus: Serialize job execution. kwalletd gets lost in nested eventloops when we send multiple openWallet() dbus calls in parallel. Thus synchronize job execution using an internal JobExecutor singleton.
Sandro Knauß
hefee-guest at moszumanska.debian.org
Sat Mar 15 19:25:44 UTC 2014
This is an automated email from the git hooks/post-receive script.
hefee-guest pushed a commit to branch master
in repository qtkeychain.
commit 42db0f2d4d3e315c1b36867f93988c540e5856a6
Author: Frank Osterfeld <osterfeld at kde.org>
Date: Fri Jul 27 23:10:47 2012 +0200
D-Bus: Serialize job execution.
kwalletd gets lost in nested eventloops when we send multiple openWallet() dbus calls in parallel.
Thus synchronize job execution using an internal JobExecutor singleton.
---
CMakeLists.txt | 3 ++-
keychain.cpp | 14 +++++-----
keychain.h | 26 +++++++++++++------
keychain_dbus.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
keychain_dbus_p.h | 45 ++++++++++++++++++++++++++++++++
keychain_mac.cpp | 4 +--
keychain_p.h | 22 ++++++++++------
keychain_win.cpp | 4 +--
8 files changed, 160 insertions(+), 35 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 472110b..1442ae4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,9 +41,10 @@ if(UNIX AND NOT APPLE)
list(APPEND qtkeychain_SOURCES keychain_dbus.cpp)
qt4_add_dbus_interface(qtkeychain_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.KWallet.xml kwallet_interface KWalletInterface)
list(APPEND qtkeychain_LIBRARIES ${QT_QTDBUS_LIBRARY})
+ list(APPEND qtkeychain_EXTRA_MOC_HEADERS keychain_dbus_p.h)
endif()
-QT4_WRAP_CPP(qtkeychain_MOC_OUTFILES keychain.h keychain_p.h)
+QT4_WRAP_CPP(qtkeychain_MOC_OUTFILES keychain.h keychain_p.h ${qtkeychain_EXTRA_MOC_HEADERS})
if(NOT QTKEYCHAIN_STATIC)
add_library(qtkeychain SHARED ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES})
diff --git a/keychain.cpp b/keychain.cpp
index 3f275ee..1694036 100644
--- a/keychain.cpp
+++ b/keychain.cpp
@@ -13,7 +13,7 @@ using namespace QKeychain;
Job::Job( const QString& service, QObject *parent )
: QObject( parent )
- , d ( new Private( service ) ) {
+ , d ( new JobPrivate( service ) ) {
}
Job::~Job() {
@@ -74,7 +74,7 @@ void Job::setErrorString( const QString& errorString ) {
ReadPasswordJob::ReadPasswordJob( const QString& service, QObject* parent )
: Job( service, parent )
- , d( new Private( this ) )
+ , d( new ReadPasswordJobPrivate( this ) )
{}
ReadPasswordJob::~ReadPasswordJob() {
@@ -103,7 +103,7 @@ void ReadPasswordJob::doStart() {
WritePasswordJob::WritePasswordJob( const QString& service, QObject* parent )
: Job( service, parent )
- , d( new Private( this ) ) {
+ , d( new WritePasswordJobPrivate( this ) ) {
}
WritePasswordJob::~WritePasswordJob() {
@@ -120,12 +120,12 @@ void WritePasswordJob::setKey( const QString& key ) {
void WritePasswordJob::setBinaryData( const QByteArray& data ) {
d->binaryData = data;
- d->mode = Private::Binary;
+ d->mode = WritePasswordJobPrivate::Binary;
}
void WritePasswordJob::setTextData( const QString& data ) {
d->textData = data;
- d->mode = Private::Text;
+ d->mode = WritePasswordJobPrivate::Text;
}
void WritePasswordJob::doStart() {
@@ -134,7 +134,7 @@ void WritePasswordJob::doStart() {
DeletePasswordJob::DeletePasswordJob( const QString& service, QObject* parent )
: Job( service, parent )
- , d( new Private( this ) ) {
+ , d( new DeletePasswordJobPrivate( this ) ) {
}
DeletePasswordJob::~DeletePasswordJob() {
@@ -158,7 +158,7 @@ void DeletePasswordJob::setKey( const QString& key ) {
d->key = key;
}
-void DeletePasswordJob::Private::jobFinished( Job* job ) {
+void DeletePasswordJobPrivate::jobFinished( Job* job ) {
q->setError( job->error() );
q->setErrorString( job->errorString() );
q->emitFinished();
diff --git a/keychain.h b/keychain.h
index ffd3b8b..0eab557 100644
--- a/keychain.h
+++ b/keychain.h
@@ -32,6 +32,9 @@ enum Error {
OtherError /**< Something else went wrong (errorString() might provide details) */
};
+class JobExecutor;
+class JobPrivate;
+
class QKEYCHAIN_EXPORT Job : public QObject {
Q_OBJECT
public:
@@ -63,10 +66,11 @@ protected:
void emitFinishedWithError(Error, const QString& errorString);
private:
- class Private;
- Private* const d;
+ JobPrivate* const d;
};
+class ReadPasswordJobPrivate;
+
class QKEYCHAIN_EXPORT ReadPasswordJob : public Job {
Q_OBJECT
public:
@@ -83,10 +87,13 @@ protected:
void doStart();
private:
- class Private;
- Private* const d;
+ friend class QKeychain::ReadPasswordJobPrivate;
+ friend class QKeychain::JobExecutor;
+ ReadPasswordJobPrivate* const d;
};
+class WritePasswordJobPrivate;
+
class QKEYCHAIN_EXPORT WritePasswordJob : public Job {
Q_OBJECT
public:
@@ -103,10 +110,13 @@ protected:
void doStart();
private:
- class Private;
- Private* const d;
+ friend class QKeychain::JobExecutor;
+ friend class QKeychain::WritePasswordJobPrivate;
+ WritePasswordJobPrivate* const d;
};
+class DeletePasswordJobPrivate;
+
class QKEYCHAIN_EXPORT DeletePasswordJob : public Job {
Q_OBJECT
public:
@@ -120,8 +130,8 @@ protected:
void doStart();
private:
- class Private;
- Private* const d;
+ friend class QKeychain::DeletePasswordJobPrivate;
+ DeletePasswordJobPrivate* const d;
};
} // namespace QtKeychain
diff --git a/keychain_dbus.cpp b/keychain_dbus.cpp
index 7273e74..c142507 100644
--- a/keychain_dbus.cpp
+++ b/keychain_dbus.cpp
@@ -7,19 +7,78 @@
* details, check the accompanying file 'COPYING'. *
*****************************************************************************/
#include "keychain_p.h"
+#include "keychain_dbus_p.h"
#include <QSettings>
using namespace QKeychain;
-void ReadPasswordJob::Private::doStart() {
+JobExecutor::JobExecutor()
+ : QObject( 0 )
+ , m_runningJob( 0 )
+{
+}
+
+void JobExecutor::enqueue( Job* job ) {
+ m_queue.append( job );
+ startNextIfNoneRunning();
+}
+
+void JobExecutor::startNextIfNoneRunning() {
+ if ( m_queue.isEmpty() || m_runningJob )
+ return;
+ QPointer<Job> next;
+ while ( !next && !m_queue.isEmpty() ) {
+ next = m_queue.first();
+ m_queue.pop_front();
+ }
+ if ( next ) {
+ connect( next, SIGNAL(finished(QKeychain::Job*)), this, SLOT(jobFinished(QKeychain::Job*)) );
+ connect( next, SIGNAL(destroyed(QObject*)), this, SLOT(jobDestroyed(QObject*)) );
+ m_runningJob = next;
+ if ( ReadPasswordJob* rpj = qobject_cast<ReadPasswordJob*>( m_runningJob ) )
+ rpj->d->scheduledStart();
+ else if ( WritePasswordJob* wpj = qobject_cast<WritePasswordJob*>( m_runningJob) )
+ wpj->d->scheduledStart();
+ }
+}
+
+void JobExecutor::jobDestroyed( QObject* object ) {
+ Q_UNUSED( object ) // for release mode
+ Q_ASSERT( object == m_runningJob );
+ m_runningJob->disconnect( this );
+ m_runningJob = 0;
+ startNextIfNoneRunning();
+}
+
+void JobExecutor::jobFinished( Job* job ) {
+ Q_UNUSED( job ) // for release mode
+ Q_ASSERT( job == m_runningJob );
+ m_runningJob->disconnect( this );
+ m_runningJob = 0;
+ startNextIfNoneRunning();
+}
+
+JobExecutor* JobExecutor::s_instance = 0;
+
+JobExecutor* JobExecutor::instance() {
+ if ( !s_instance )
+ s_instance = new JobExecutor;
+ return s_instance;
+}
+
+void ReadPasswordJobPrivate::doStart() {
+ JobExecutor::instance()->enqueue( q );
+}
+
+void ReadPasswordJobPrivate::scheduledStart() {
iface = new org::kde::KWallet( QLatin1String("org.kde.kwalletd"), QLatin1String("/modules/kwalletd"), QDBusConnection::sessionBus(), this );
const QDBusPendingReply<int> reply = iface->open( QLatin1String("kdewallet"), 0, q->service() );
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this );
connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
}
-void ReadPasswordJob::Private::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
+void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
watcher->deleteLater();
const QDBusPendingReply<int> reply = *watcher;
if ( reply.isError() ) {
@@ -43,7 +102,7 @@ void ReadPasswordJob::Private::kwalletOpenFinished( QDBusPendingCallWatcher* wat
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletEntryTypeFinished(QDBusPendingCallWatcher*)) );
}
-void ReadPasswordJob::Private::kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ) {
+void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ) {
watcher->deleteLater();
if ( watcher->isError() ) {
const QDBusError err = watcher->error();
@@ -62,7 +121,7 @@ void ReadPasswordJob::Private::kwalletEntryTypeFinished( QDBusPendingCallWatcher
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletReadFinished(QDBusPendingCallWatcher*)) );
}
-void ReadPasswordJob::Private::kwalletReadFinished( QDBusPendingCallWatcher* watcher ) {
+void ReadPasswordJobPrivate::kwalletReadFinished( QDBusPendingCallWatcher* watcher ) {
watcher->deleteLater();
if ( watcher->isError() ) {
const QDBusError err = watcher->error();
@@ -80,14 +139,18 @@ void ReadPasswordJob::Private::kwalletReadFinished( QDBusPendingCallWatcher* wat
q->emitFinished();
}
-void WritePasswordJob::Private::doStart() {
+void WritePasswordJobPrivate::doStart() {
+ JobExecutor::instance()->enqueue( q );
+}
+
+void WritePasswordJobPrivate::scheduledStart() {
iface = new org::kde::KWallet( QLatin1String("org.kde.kwalletd"), QLatin1String("/modules/kwalletd"), QDBusConnection::sessionBus(), this );
const QDBusPendingReply<int> reply = iface->open( QLatin1String("kdewallet"), 0, q->service() );
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this );
connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
}
-void WritePasswordJob::Private::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
+void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
watcher->deleteLater();
QDBusPendingReply<int> reply = *watcher;
if ( reply.isError() ) {
@@ -116,7 +179,7 @@ void WritePasswordJob::Private::kwalletOpenFinished( QDBusPendingCallWatcher* wa
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletWriteFinished(QDBusPendingCallWatcher*)) );
}
-void WritePasswordJob::Private::kwalletWriteFinished( QDBusPendingCallWatcher* watcher ) {
+void WritePasswordJobPrivate::kwalletWriteFinished( QDBusPendingCallWatcher* watcher ) {
watcher->deleteLater();
QDBusPendingReply<int> reply = *watcher;
if ( reply.isError() ) {
diff --git a/keychain_dbus_p.h b/keychain_dbus_p.h
new file mode 100644
index 0000000..fee59eb
--- /dev/null
+++ b/keychain_dbus_p.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ * Copyright (C) 2012 Frank Osterfeld <frank.osterfeld at gmail.com> *
+ * *
+ * This program is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution *
+ * details, check the accompanying file 'COPYING'. *
+ *****************************************************************************/
+
+#ifndef QTKEYCHAIN_KEYCHAIN_DBUS_P_H
+#define QTKEYCHAIN_KEYCHAIN_DBUS_P_H
+
+#include "keychain.h"
+
+#include <QPointer>
+#include <QVector>
+
+namespace QKeychain {
+
+class JobExecutor : public QObject {
+ Q_OBJECT
+public:
+
+ static JobExecutor* instance();
+
+ void enqueue( Job* job );
+
+private:
+ explicit JobExecutor();
+ void startNextIfNoneRunning();
+
+private Q_SLOTS:
+ void jobFinished( QKeychain::Job* );
+ void jobDestroyed( QObject* object );
+
+private:
+ static JobExecutor* s_instance;
+ Job* m_runningJob;
+ QVector<QPointer<Job> > m_queue;
+};
+
+}
+
+#endif
+
diff --git a/keychain_mac.cpp b/keychain_mac.cpp
index d81ecf5..4515f99 100644
--- a/keychain_mac.cpp
+++ b/keychain_mac.cpp
@@ -61,7 +61,7 @@ static OSStatus readPw( QByteArray* pw,
return ret;
}
-void ReadPasswordJob::Private::doStart()
+void ReadPasswordJobPrivate::doStart()
{
QString errorString;
Error error = NoError;
@@ -141,7 +141,7 @@ static QKeychain::Error writeEntryImpl( const QString& service,
return NoError;
}
-void WritePasswordJob::Private::doStart()
+void WritePasswordJobPrivate::doStart()
{
QString errorString;
Error error = NoError;
diff --git a/keychain_p.h b/keychain_p.h
index 0268aaf..c2a1dee 100644
--- a/keychain_p.h
+++ b/keychain_p.h
@@ -29,10 +29,12 @@ class QDBusPendingCallWatcher;
namespace QKeychain {
-class Job::Private : public QObject {
+class JobExecutor;
+
+class JobPrivate : public QObject {
Q_OBJECT
public:
- Private( const QString& service_ )
+ JobPrivate( const QString& service_ )
: error( NoError )
, service( service_ )
, autoDelete( true ) {}
@@ -44,10 +46,10 @@ public:
QPointer<QSettings> settings;
};
-class ReadPasswordJob::Private : public QObject {
+class ReadPasswordJobPrivate : public QObject {
Q_OBJECT
public:
- explicit Private( ReadPasswordJob* qq ) : q( qq ), walletHandle( 0 ), dataType( Text ) {}
+ explicit ReadPasswordJobPrivate( ReadPasswordJob* qq ) : q( qq ), walletHandle( 0 ), dataType( Text ) {}
void doStart();
ReadPasswordJob* const q;
QByteArray data;
@@ -61,6 +63,8 @@ public:
#if defined(Q_OS_UNIX) && !defined(Q_WS_MAC)
org::kde::KWallet* iface;
+ friend class QKeychain::JobExecutor;
+ void scheduledStart();
private Q_SLOTS:
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
@@ -75,10 +79,10 @@ private Q_SLOTS:
};
-class WritePasswordJob::Private : public QObject {
+class WritePasswordJobPrivate : public QObject {
Q_OBJECT
public:
- explicit Private( WritePasswordJob* qq ) : q( qq ), mode( Delete ) {}
+ explicit WritePasswordJobPrivate( WritePasswordJob* qq ) : q( qq ), mode( Delete ) {}
void doStart();
enum Mode {
Delete,
@@ -93,6 +97,8 @@ public:
#if defined(Q_OS_UNIX) && !defined(Q_WS_MAC)
org::kde::KWallet* iface;
+ friend class QKeychain::JobExecutor;
+ void scheduledStart();
private Q_SLOTS:
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
@@ -104,10 +110,10 @@ private Q_SLOTS:
#endif
};
-class DeletePasswordJob::Private : public QObject {
+class DeletePasswordJobPrivate : public QObject {
Q_OBJECT
public:
- explicit Private( DeletePasswordJob* qq ) : q( qq ) {}
+ explicit DeletePasswordJobPrivate( DeletePasswordJob* qq ) : q( qq ) {}
void doStart();
DeletePasswordJob* const q;
QString key;
diff --git a/keychain_win.cpp b/keychain_win.cpp
index 76b4116..509c0cb 100644
--- a/keychain_win.cpp
+++ b/keychain_win.cpp
@@ -17,7 +17,7 @@
using namespace QKeychain;
-void ReadPasswordJob::Private::doStart() {
+void ReadPasswordJobPrivate::doStart() {
//Use settings member if there, create local settings object if not
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
QSettings* actual = q->settings() ? q->settings() : local.get();
@@ -52,7 +52,7 @@ void ReadPasswordJob::Private::doStart() {
q->emitFinished();
}
-void WritePasswordJob::Private::doStart() {
+void WritePasswordJobPrivate::doStart() {
if ( mode == Delete ) {
//Use settings member if there, create local settings object if not
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/qtkeychain.git
More information about the Pkg-owncloud-commits
mailing list