Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-75007

QML Singleton creation in multi-threaded application causes errors

XMLWordPrintable

    • Linux/X11

      When running multiple threads

      • each one having a QQmlEngine
      • each one running an identical QML file
      • each one calling a method which instanciates a singleton object (QML singleton)

      i get the following warnings and errors (not always):

      • std::bad_alloc exception and application crashes
      • Type conversion already registered from type ... to ...
      • TypeError: Property 'foo' of object Qst_QMLTYPE_1(0x7fcd84022b50) is not a function
      • Trying to construct an instance of an invalid type, type id: <some number>

      Please find attached a minimal test case that reproduces that behavior. Some of the warnings/errors go away if I protect QQmlComponent constructor and create() by a mutex. However, I think that this only masks the problem because it makes it less likely that both threads instantiate the singletons at the same time. The singleton objects are instantiated when the run() method in file.qml is invoked.

      Looks like this one hits several concurrency problems in the Qt meta type system and QML type loader.

      Here is the code:

      #include <QtCore>
      #include <QtQml>
      
      QMutex mutex;
      
      class Runnable : public QRunnable {
      public:
          virtual void run() final;
      };
      
      void Runnable::run() {
          QQmlEngine engine;
      //    QMutexLocker lock(&mutex);
          QQmlComponent component(&engine,QUrl::fromLocalFile("file.qml"));
          QObject* object = component.create(engine.rootContext());
      //    lock.unlock();
          Q_ASSERT(component.errors().isEmpty());
      
          QMetaObject::invokeMethod(object, "run");
      }
      
      void doSomething() {
          for (int i = 0; i < 12; i++) {
              QThreadPool::globalInstance()->start(new Runnable());
          }
          QThreadPool::globalInstance()->waitForDone();
          QCoreApplication::exit(0);
      }
      
      int main(int argc, char* argv[]) {
          QCoreApplication app(argc, argv);
          QThreadPool::globalInstance()->setMaxThreadCount(2);
          QTimer::singleShot(1, &doSomething);
          return app.exec();
      }
      
      // Qst.qml
      import QtQml 2.0
      pragma Singleton
      
      QtObject {
      
          function foo() {
              for (var i = 0; i < 1000; i++) {
      
              }
          }
      }
      

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            rweickelt Richard Weickelt
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:

                There are no open Gerrit changes