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

QJSEngine crash when called from a thread

    XMLWordPrintable

Details

    • Windows

    Description

      Hi

       

      I have a crash inside the QV4 javascript engine, when I call scripts from a worker thread. I know that the JS engine is not multithread-safe, but I use it only in this thread, so there should be no concurrent access.

       

      The crash is similar to what is described in https://bugreports.qt.io/browse/QTBUG-75939. It's supposed to be fixed in Qt 5.13.1 but that's the version I use.

       

      Call stack:

       

      Qt5Qmld.dll!QV4::Value::value() Ligne 141 C++
      Qt5Qmld.dll!QV4::Value::int_32() Ligne 195 C++
      Qt5Qmld.dll!QV4::PersistentValueStorage::allocate() Ligne 208 C++
      Qt5Qmld.dll!QJSValuePrivate::setValue(QJSValue * jsval, QV4::ExecutionEngine * engine, unsigned __int64 v) Ligne 101 C++
      Qt5Qmld.dll!QJSValue::QJSValue(QV4::ExecutionEngine * e, unsigned __int64 val) Ligne 206 C++
      Qt5Qmld.dll!QJSValue::call(const QList<QJSValue> & args) Ligne 774 C++

       

       

       

      Value *v = p->values + p->header.freeList;
      p->header.freeList = v->int_32();
      

      Seems like p->header.freeList holds some invalid value, and produces an invalid pointer.

       

      Minimal code that reproduces the problem:

      #include <QCoreApplication>
      #include <QJSEngine>
      #include <QThread>
      #include <QTimer>
      
      int main(int argc, char** argv)
      {
          QCoreApplication app(argc, argv);
          QJSEngine engine;
          engine.installExtensions(QJSEngine::ConsoleExtension);
          engine.evaluate("var iteration = 0;");
      
          auto function = engine.evaluate(R"((
              function()
              {
                  if (++iteration % 100 == 0)
                      console.log(iteration);
              }
          ))");
      
          QThread thread;
          thread.start();
      
          QTimer timer;
          QObject::connect(&timer, &QTimer::timeout, &engine, [&]{function.call();}, Qt::DirectConnection);
          timer.moveToThread(&thread);
          QMetaObject::invokeMethod(&timer, "start", Q_ARG(int, 0));
      
          return app.exec();
      }
      

      Sometimes the output just stops, there's no crash. To increase the chances of crash, passing dummy arguments to the function call helps a lot.

       

      Of course, doing the same thing in the main thread (commenting the call to timer.moveToThread(&thread)) works perfectly.

       

      Thanks

       

       

       

       

      Attachments

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

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            laurentgom Laurent
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes