Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Strange errors from QThread

Strange errors from QThread

Scheduled Pinned Locked Moved Solved General and Desktop
qthreadqbackingstore
6 Posts 4 Posters 5.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SolaVitae
    wrote on 10 Apr 2018, 11:12 last edited by SolaVitae 4 Oct 2018, 11:13
    #1

    I have a QThread that downloads icons via cURL from a wikia, and for some reason whenever i execute the download, or skip it if the file already exists my program crashes with a weird error, theres quite a few lines of code that arent really neccessary for this error so i've tried to narrow it down to just the pertinent parts

    The Thread creator

    while (q.next()) {
                   ...
    		if (!fileExists(istemp->iconPath)) {
    			QThread *itemRetriever = new QThread;
    			threadsRemaining++;
    			ItemSearchIconWorker *icw = new ItemSearchIconWorker(istemp, &threadsRemaining);
    			icw->itemWidget = istemp;
    			QObject::connect(itemRetriever, SIGNAL(started()), icw, SLOT(process()));
    			QObject::connect(icw, SIGNAL(finished()), itemRetriever, SLOT(quit()));
    			QObject::connect(icw, SIGNAL(finished()), icw, SLOT(deleteLater()));
    			QObject::connect(itemRetriever, SIGNAL(finished()), itemRetriever, SLOT(deleteLater()));
    			icw->moveToThread(itemRetriever);
    			threads.insert(threads.end(), itemRetriever);
    			connect(icw, SIGNAL(iconDLComplete()), this, SLOT(threadComplete()));
    			totalThreads++;
    		}
    		else {
    			QIcon *newIcon = new QIcon;
    			newIcon->addFile(istemp->iconPath, QSize(28, 28));
    			istemp->itemIconLabel->setPixmap(newIcon->pixmap(newIcon->actualSize(QSize(28, 28))));
    		}
    		index++;
    		
    	}
    	for (QThread *t : threads) {
    		t->start();
    	}
    

    The Worker's proccess()

    	ItemSearchItem *temp = dynamic_cast<ItemSearchItem*>(istemp);
    
    
    	//downloadFileS("abcd", "abcd");
            // This usually downloads the requested image, but is commented out for testing (still breaks even without it)
    
    	QIcon *tempIcon = new QIcon;
    	tempIcon->addFile(temp->iconPath, QSize(28,28));
    	temp->itemIconLabel->setPixmap(tempIcon->pixmap(tempIcon->actualSize(QSize(28, 28))));
    
    	emit iconDLComplete();
    
    	emit finished();
    

    The threadComplete slot just decreases threadsRemaining by 1, then emits lookupFinished() if its 0

    lookupFinished is connected to a slot that fills a list, but it never reaches it, as it just crashes right before

    The error i get when it crashes is

    ASSERT failure in QVector<T>::at: "index out of range", file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 424
    Debug Error!
    
    Program: ...x64\Debug\Qt5Cored.dll
    Module: 5.10.1
    File: c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h
    Line: 424
    
    ASSERT failure in QVector<T>::at: "index out of range", file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 424
    
    (Press Retry to debug the application)
    QWidget::repaint: Recursive repaint detected
    

    i also get this message

    QBackingStore::endPaint() called with active painter on backingstore paint device
    

    That message spams itself until i close the program, and if i trace it in debug the call stack just leads me to my programs .exec() in my main() function, and i'm not using any QVectors

    And this is the call stack from the error

    https://i.imgur.com/Ckb8SNn.png

    K 1 Reply Last reply 10 Apr 2018, 14:41
    0
    • V Offline
      V Offline
      VRonin
      wrote on 10 Apr 2018, 11:49 last edited by VRonin 4 Oct 2018, 11:49
      #2

      from http://doc.qt.io/qt-5/thread-basics.html

      All widgets and several related classes, for example QPixmap, don't work in secondary threads.

      Never manipulate the UI (itemIconLabel->setPixmap) or QPixmaps (tempIcon->pixmap) from secondary threads

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      7
      • S SolaVitae
        10 Apr 2018, 11:12

        I have a QThread that downloads icons via cURL from a wikia, and for some reason whenever i execute the download, or skip it if the file already exists my program crashes with a weird error, theres quite a few lines of code that arent really neccessary for this error so i've tried to narrow it down to just the pertinent parts

        The Thread creator

        while (q.next()) {
                       ...
        		if (!fileExists(istemp->iconPath)) {
        			QThread *itemRetriever = new QThread;
        			threadsRemaining++;
        			ItemSearchIconWorker *icw = new ItemSearchIconWorker(istemp, &threadsRemaining);
        			icw->itemWidget = istemp;
        			QObject::connect(itemRetriever, SIGNAL(started()), icw, SLOT(process()));
        			QObject::connect(icw, SIGNAL(finished()), itemRetriever, SLOT(quit()));
        			QObject::connect(icw, SIGNAL(finished()), icw, SLOT(deleteLater()));
        			QObject::connect(itemRetriever, SIGNAL(finished()), itemRetriever, SLOT(deleteLater()));
        			icw->moveToThread(itemRetriever);
        			threads.insert(threads.end(), itemRetriever);
        			connect(icw, SIGNAL(iconDLComplete()), this, SLOT(threadComplete()));
        			totalThreads++;
        		}
        		else {
        			QIcon *newIcon = new QIcon;
        			newIcon->addFile(istemp->iconPath, QSize(28, 28));
        			istemp->itemIconLabel->setPixmap(newIcon->pixmap(newIcon->actualSize(QSize(28, 28))));
        		}
        		index++;
        		
        	}
        	for (QThread *t : threads) {
        		t->start();
        	}
        

        The Worker's proccess()

        	ItemSearchItem *temp = dynamic_cast<ItemSearchItem*>(istemp);
        
        
        	//downloadFileS("abcd", "abcd");
                // This usually downloads the requested image, but is commented out for testing (still breaks even without it)
        
        	QIcon *tempIcon = new QIcon;
        	tempIcon->addFile(temp->iconPath, QSize(28,28));
        	temp->itemIconLabel->setPixmap(tempIcon->pixmap(tempIcon->actualSize(QSize(28, 28))));
        
        	emit iconDLComplete();
        
        	emit finished();
        

        The threadComplete slot just decreases threadsRemaining by 1, then emits lookupFinished() if its 0

        lookupFinished is connected to a slot that fills a list, but it never reaches it, as it just crashes right before

        The error i get when it crashes is

        ASSERT failure in QVector<T>::at: "index out of range", file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 424
        Debug Error!
        
        Program: ...x64\Debug\Qt5Cored.dll
        Module: 5.10.1
        File: c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h
        Line: 424
        
        ASSERT failure in QVector<T>::at: "index out of range", file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 424
        
        (Press Retry to debug the application)
        QWidget::repaint: Recursive repaint detected
        

        i also get this message

        QBackingStore::endPaint() called with active painter on backingstore paint device
        

        That message spams itself until i close the program, and if i trace it in debug the call stack just leads me to my programs .exec() in my main() function, and i'm not using any QVectors

        And this is the call stack from the error

        https://i.imgur.com/Ckb8SNn.png

        K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 10 Apr 2018, 14:41 last edited by
        #3

        In addition to @VRonin, you don't need the hundreds of threads. Either use a (thread-safe) queue for the jobs, or simply QtConcurrent::run to use the already existing thread pool. Threads are rather heavy on Linux, so it makes little sense to create them to fetch single item over the network and then destroy them for no obvious reason.

        Read and abide by the Qt Code of Conduct

        1 Reply Last reply
        3
        • V Offline
          V Offline
          VRonin
          wrote on 10 Apr 2018, 14:47 last edited by
          #4

          You can also use a single QNetworkAccessManager instead of cUrl to download the icons with no need to implement multithreading at all

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          4
          • B Offline
            B Offline
            Buckwheat
            wrote on 10 Apr 2018, 14:59 last edited by
            #5

            @SolaVitae

            Along with what @VRonin was saying about accessing (updating) the UI from other than the main thread, you must be very careful using QVector, QList, QMap, std::vector, std::list, std::map, etc. across threads as they are intrinsically NOT multi-thread safe. Synchronizing mechanisms must be employed.

            Using thread pools is very effective for managing your threads and resources.

            Dave Fileccia

            1 Reply Last reply
            3
            • S Offline
              S Offline
              SolaVitae
              wrote on 11 Apr 2018, 05:39 last edited by
              #6

              I feel like this is a perfect personification of the "came searching for copper but found gold meme", Sometime in the past I acknowledged that modifying UI elements in a secondary thread caused crashes, I even fixed it, then when I moved my project from computer to computer i must have copied an old file or something, and forgot that that was a no-no. But I digress, not only did this thread solve my problem, it also showed me a way to ditch cURL, and rely solely on QT, as well as circumvent the necessity of the threading in the first place, so thank you all for answering my question and more @Buckwheat / @VRonin /@kshegunov

              1 Reply Last reply
              0

              6/6

              11 Apr 2018, 05:39

              • Login

              • Login or register to search.
              6 out of 6
              • First post
                6/6
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved