@@ -26,15 +26,22 @@ void Setup::setCleanupTimeout(unsigned long timeout)
2626void Setup::removeSetup (const QString &name, bool waitForFinished)
2727{
2828 QMutexLocker _ (&SetupPrivate::setupMutex);
29+ if (!SetupPrivate::engines.contains (name))
30+ return ;
2931 auto mThread = SetupPrivate::engines.value (name);
3032 _.unlock (); // unlock first
3133
3234 if (mThread ) {
3335 mThread ->stopEngine ();
3436 if (waitForFinished)
3537 mThread ->waitAndTerminate (SetupPrivate::timeout);
36- } else // no there -> remove defaults (either already removed does nothing, or remove passive)
38+ } else {
39+ // was set but null -> must be passive -> remove passive defaults
3740 DefaultsPrivate::removeDefaults (name);
41+ // and remove from setup
42+ _.relock ();
43+ SetupPrivate::engines.remove (name);
44+ }
3845}
3946
4047QStringList Setup::keystoreProviders ()
@@ -428,9 +435,6 @@ Setup &Setup::setAccountTrusted(const QByteArray &importData, const QString &pas
428435
429436void Setup::create (const QString &name)
430437{
431- if (QThread::currentThread () != qApp->thread ())
432- qCWarning (qdssetup) << " Setup::create should only be called from the main thread" ;
433-
434438 QMutexLocker _ (&SetupPrivate::setupMutex);
435439 if (SetupPrivate::engines.contains (name))
436440 throw SetupExistsException (name);
@@ -450,27 +454,29 @@ void Setup::create(const QString &name)
450454 if (d->initialImport .isSet ())
451455 engine->prepareInitialAccount (d->initialImport );
452456
453- // create and connect the new thread
454- auto thread = new EngineThread{name, engine, lockFile};
455- // once the thread finished, clear the engine from the cache of known ones
456- QObject::connect (thread, &QThread::finished, [name](){
457- QMutexLocker _cn (&SetupPrivate::setupMutex);
458- SetupPrivate::engines.remove (name);
459- _cn.unlock ();
460- DefaultsPrivate::removeDefaults (name);
461- }); // queued connection, sent from within the thread to thread object on current thread
462-
463- // start the thread and cache engine data
457+ // create and start the engine in its thread
458+ QSharedPointer<EngineThread> thread {
459+ new EngineThread{name, engine, lockFile},
460+ &SetupPrivate::deleteThread
461+ };
464462 SetupPrivate::engines.insert (name, thread);
465463 thread->startEngine ();
466464}
467465
468466bool Setup::createPassive (const QString &name, int timeout)
469467{
468+ QMutexLocker _ (&SetupPrivate::setupMutex);
469+ if (SetupPrivate::engines.contains (name))
470+ throw SetupExistsException (name);
471+
470472 // create storage dir and defaults
471473 auto storageDir = d->createStorageDir (name);
472474 d->createDefaults (name, storageDir, true );
473475
476+ // theoretically "ready" -> save (with null engine) and unlock
477+ SetupPrivate::engines.insert (name, {});
478+ _.unlock ();
479+
474480 // wait for the setup to complete initialization
475481 auto defaults = DefaultsPrivate::obtainDefaults (name);
476482 auto isCreated = false ;
@@ -501,28 +507,30 @@ bool Setup::createPassive(const QString &name, int timeout)
501507
502508const QString SetupPrivate::DefaultLocalDir = QStringLiteral(" ./qtdatasync/default" );
503509QMutex SetupPrivate::setupMutex (QMutex::Recursive);
504- QHash<QString, QPointer <EngineThread>> SetupPrivate::engines;
510+ QHash<QString, QSharedPointer <EngineThread>> SetupPrivate::engines;
505511unsigned long SetupPrivate::timeout = ULONG_MAX;
506512
507513void SetupPrivate::cleanupHandler ()
508514{
509515 QMutexLocker _ (&setupMutex);
510- auto threads = engines. values () ;
516+ auto threads = engines;
511517 engines.clear ();
512518 _.unlock ();
513519
514- for ( auto &thread : threads) {
515- if (thread-> stopEngine () &&
516- thread-> thread () != QThread::currentThread ()) {
517- qCCritical (qdssetup) << " Stopping datasync thread " << thread-> name ()
518- << " from the main thread even though it was created on a different thread! "
519- << " This can lead to synchronization errors. You should always stop all other threads before quitting the application. " ;
520- }
520+ // stop/remove all running setups
521+ for ( auto it = threads. constBegin (); it != threads. constEnd (); it++) {
522+ const auto & thread = it. value ();
523+ if (thread) // active setup -> send stip
524+ thread-> stopEngine ();
525+ else // passive setup -> simply remove defaults
526+ DefaultsPrivate::removeDefaults (it. key ());
521527 }
522- for (auto &thread : threads)
523- thread->waitAndTerminate (timeout);
524528
525- DefaultsPrivate::clearDefaults ();
529+ // wait for active setups to finish
530+ for (auto &thread : threads) {
531+ if (thread)
532+ thread->waitAndTerminate (timeout);
533+ }
526534}
527535
528536unsigned long SetupPrivate::currentTimeout ()
@@ -595,9 +603,14 @@ SetupPrivate::SetupPrivate() :
595603 {Defaults::SignScheme, Setup::ECDSA_ECP_SHA3_512},
596604 {Defaults::CryptScheme, Setup::ECIES_ECP_SHA3_512},
597605 {Defaults::SymScheme, Setup::AES_EAX}
598- }
606+ }
599607{}
600608
609+ void SetupPrivate::deleteThread (EngineThread *thread)
610+ {
611+ thread->deleteLater ();
612+ }
613+
601614// ------------- Exceptions -------------
602615
603616SetupException::SetupException (const QString &setupName, const QString &message) :
0 commit comments