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. Debug with QSignalSpy a timer object causing crashes
Forum Updated to NodeBB v4.3 + New Features

Debug with QSignalSpy a timer object causing crashes

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 4 Posters 3.3k Views 2 Watching
  • 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.
  • G giusdbg

    @JonB Screenshot_20230606_024927.png

    Axel SpoerlA Online
    Axel SpoerlA Online
    Axel Spoerl
    Moderators
    wrote on last edited by
    #7

    @giusdbg
    The stack trace shows the crash in the QObjectPrivate. Hard to say for sure without seeing your code. However, that part gets deleted first before the actual object is getting deleted. So most likely the crash is a UAF.

    Software Engineer
    The Qt Company, Oslo

    G 1 Reply Last reply
    1
    • Axel SpoerlA Axel Spoerl

      @giusdbg
      The stack trace shows the crash in the QObjectPrivate. Hard to say for sure without seeing your code. However, that part gets deleted first before the actual object is getting deleted. So most likely the crash is a UAF.

      G Offline
      G Offline
      giusdbg
      wrote on last edited by
      #8

      @Axel-Spoerl I've tried to analyze the stack trace, but I couldn't figure out which objects or events in my program were involved.

      I just have the unfortunate feeling that the stack trace is not related to the problem itself, but only to the application shutdown caused by the problem.

      P.S. UAF?

      JonBJ 1 Reply Last reply
      0
      • G giusdbg

        @Axel-Spoerl I've tried to analyze the stack trace, but I couldn't figure out which objects or events in my program were involved.

        I just have the unfortunate feeling that the stack trace is not related to the problem itself, but only to the application shutdown caused by the problem.

        P.S. UAF?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #9

        @giusdbg
        Your stack trace shows qprocess.cpp:1089. That is probably in QProcessPrivate::_q_processDied(), somewhere around https://code.woboq.org/kde/qt4/src/corelib/io/qprocess.cpp.html#1089. Does your code spawn other OS processes via QProcess?

        G 1 Reply Last reply
        0
        • JonBJ JonB

          @giusdbg
          Your stack trace shows qprocess.cpp:1089. That is probably in QProcessPrivate::_q_processDied(), somewhere around https://code.woboq.org/kde/qt4/src/corelib/io/qprocess.cpp.html#1089. Does your code spawn other OS processes via QProcess?

          G Offline
          G Offline
          giusdbg
          wrote on last edited by giusdbg
          #10

          @JonB No, or rather I think all kde applications do it by default, in fact there is a --nofork option.

          I believe it does here

          int main(int argc, char *argv[])
          {
          ................
            if(!KUniqueApplication::start())  return 0;
            KUniqueApplication a;
          ................
          
            a.setQuitOnLastWindowClosed(false);
            
            return a.exec();
          }
          

          And it occurs to me that maybe I should try running the program with --nofork for a few days, and see what happens.

          I'm talking nonsense, if it weren't for the --nofork when debugging, I wouldn't see anything in the debugger.

          Axel SpoerlA 1 Reply Last reply
          0
          • G giusdbg

            @JonB No, or rather I think all kde applications do it by default, in fact there is a --nofork option.

            I believe it does here

            int main(int argc, char *argv[])
            {
            ................
              if(!KUniqueApplication::start())  return 0;
              KUniqueApplication a;
            ................
            
              a.setQuitOnLastWindowClosed(false);
              
              return a.exec();
            }
            

            And it occurs to me that maybe I should try running the program with --nofork for a few days, and see what happens.

            I'm talking nonsense, if it weren't for the --nofork when debugging, I wouldn't see anything in the debugger.

            Axel SpoerlA Online
            Axel SpoerlA Online
            Axel Spoerl
            Moderators
            wrote on last edited by
            #11

            @giusdbg
            UAF = use after free, accessing a deleted object. That's what most likely happens.
            The code shown above doesn't have to do anything with a QSignalSpyor a timer of any nature.
            If there is reason to assume those (or one of them) cause(s) the crash, please show the code!

            Software Engineer
            The Qt Company, Oslo

            G 1 Reply Last reply
            1
            • Axel SpoerlA Axel Spoerl

              @giusdbg
              UAF = use after free, accessing a deleted object. That's what most likely happens.
              The code shown above doesn't have to do anything with a QSignalSpyor a timer of any nature.
              If there is reason to assume those (or one of them) cause(s) the crash, please show the code!

              G Offline
              G Offline
              giusdbg
              wrote on last edited by
              #12

              @Axel-Spoerl It's not possible, it's a complex program

              https://sourceforge.net/projects/ksensors-qt5/

              G 1 Reply Last reply
              0
              • G giusdbg

                @Axel-Spoerl It's not possible, it's a complex program

                https://sourceforge.net/projects/ksensors-qt5/

                G Offline
                G Offline
                giusdbg
                wrote on last edited by
                #13

                @Axel-Spoerl @JonB Maybe I have an answer (at least partial) to your questions.

                There is this part (which is called by the timer and generates events) which launches external processes to get values from the sensors.

                This uses the KProcess object which is derived from QProcess, and in my opinion is involved in the crash (maybe not directly).

                I can't show you the full code that calls this part without posting a lot of code.

                #include <QtDebug>
                
                #include <string.h>
                #include "processexec.h"
                
                ProcessExec::ProcessExec(): KProcess()
                {
                 clearData();
                 
                 connect( this, SIGNAL(readyReadStandardOutput()),this, SLOT(slotReceivedStdout()) );
                 connect( this, SIGNAL(readyReadStandardError()),this, SLOT(slotReceivedStderr()) );
                }
                
                ProcessExec::~ProcessExec(){
                }
                
                bool ProcessExec::run()
                {
                  qDebug() << "\033[91m" << "qDebug(): ProcessExec::run()" << "\033[0m";
                  
                 clearData();
                 start();
                 return true;
                }
                
                bool ProcessExec::runAndWait()
                {
                  qDebug() << "\033[91m" << "qDebug(): ProcessExec::runAndWait()" << "\033[0m";
                  
                 clearData();
                 
                 setOutputChannelMode(KProcess::SeparateChannels);
                 
                 execute();
                 
                 return true;
                }
                
                void ProcessExec::slotReceivedStdout()
                {
                //  setReadChannel(KProcess::StandardOutput);
                  
                  buffer.append ( readAllStandardOutput() );
                  
                  qDebug() << "\033[91m" << "qDebug(): ProcessExec::slotReceivedStdout(): buffer " << buffer << "\033[0m";
                }
                
                void ProcessExec::slotReceivedStderr()
                {
                  fErrors= true;
                  
                //  setReadChannel(KProcess::StandardError);
                  
                  buffer.append ( readAllStandardError() );
                  
                  qDebug() << "\033[91m" << "qDebug(): ProcessExec::slotReceivedStderr(): buffer " << buffer << "\033[0m";
                  
                }
                
                
                ........................................................
                void HDSensorsList::updateSensors()
                {
                 if(process) return;
                
                 const QObjectList *list= &children();
                 if(!list) return;
                
                 QStringList params;  
                 for ( QObjectList::ConstIterator it = list->begin(); it != list->end(); ++it ) {
                    Sensor *obj = (Sensor *)(*it);
                    
                    if(obj->monitorized())
                      params << obj->objectName();
                 }
                
                 if(params.count()>0) {
                   process= new ProcessExec;
                   *process << "hddtemp" << "-q" << params;
                   connect( process, SIGNAL(finished(int)), this, SLOT(slotProcessExited(int)) );
                   process->run();
                 }
                }
                
                void HDSensorsList::slotProcessExited(int exitCode)
                {
                 const QObjectList *list= &children();
                
                 if (!list) return;
                
                 if (process->outputErrors())
                   qWarning("HddTemp Error:\n%s", process->getStdoutData().toAscii().data());
                
                 QStringList buf = process->getStdoutData().split(QChar('\n'));
                 for(QStringList::Iterator it = buf.begin(); it != buf.end(); ++it ) {
                   for ( QObjectList::ConstIterator olIt = list->begin(); olIt != list->end(); ++olIt ) {
                     Sensor *obj = (Sensor *)(*olIt);
                 
                     QRegExp rx(QString(obj->objectName()) + QString(":\\s+.+:\\s+(\\d+).*C"));
                     if (rx.indexIn((*it)) > -1)
                       obj->setValue(rx.cap(1).toDouble(), Sensor::dgCelsius); 
                   }
                 }
                 delete process;
                 process= 0;
                }
                ........................................................
                
                G 1 Reply Last reply
                0
                • G giusdbg

                  @Axel-Spoerl @JonB Maybe I have an answer (at least partial) to your questions.

                  There is this part (which is called by the timer and generates events) which launches external processes to get values from the sensors.

                  This uses the KProcess object which is derived from QProcess, and in my opinion is involved in the crash (maybe not directly).

                  I can't show you the full code that calls this part without posting a lot of code.

                  #include <QtDebug>
                  
                  #include <string.h>
                  #include "processexec.h"
                  
                  ProcessExec::ProcessExec(): KProcess()
                  {
                   clearData();
                   
                   connect( this, SIGNAL(readyReadStandardOutput()),this, SLOT(slotReceivedStdout()) );
                   connect( this, SIGNAL(readyReadStandardError()),this, SLOT(slotReceivedStderr()) );
                  }
                  
                  ProcessExec::~ProcessExec(){
                  }
                  
                  bool ProcessExec::run()
                  {
                    qDebug() << "\033[91m" << "qDebug(): ProcessExec::run()" << "\033[0m";
                    
                   clearData();
                   start();
                   return true;
                  }
                  
                  bool ProcessExec::runAndWait()
                  {
                    qDebug() << "\033[91m" << "qDebug(): ProcessExec::runAndWait()" << "\033[0m";
                    
                   clearData();
                   
                   setOutputChannelMode(KProcess::SeparateChannels);
                   
                   execute();
                   
                   return true;
                  }
                  
                  void ProcessExec::slotReceivedStdout()
                  {
                  //  setReadChannel(KProcess::StandardOutput);
                    
                    buffer.append ( readAllStandardOutput() );
                    
                    qDebug() << "\033[91m" << "qDebug(): ProcessExec::slotReceivedStdout(): buffer " << buffer << "\033[0m";
                  }
                  
                  void ProcessExec::slotReceivedStderr()
                  {
                    fErrors= true;
                    
                  //  setReadChannel(KProcess::StandardError);
                    
                    buffer.append ( readAllStandardError() );
                    
                    qDebug() << "\033[91m" << "qDebug(): ProcessExec::slotReceivedStderr(): buffer " << buffer << "\033[0m";
                    
                  }
                  
                  
                  ........................................................
                  void HDSensorsList::updateSensors()
                  {
                   if(process) return;
                  
                   const QObjectList *list= &children();
                   if(!list) return;
                  
                   QStringList params;  
                   for ( QObjectList::ConstIterator it = list->begin(); it != list->end(); ++it ) {
                      Sensor *obj = (Sensor *)(*it);
                      
                      if(obj->monitorized())
                        params << obj->objectName();
                   }
                  
                   if(params.count()>0) {
                     process= new ProcessExec;
                     *process << "hddtemp" << "-q" << params;
                     connect( process, SIGNAL(finished(int)), this, SLOT(slotProcessExited(int)) );
                     process->run();
                   }
                  }
                  
                  void HDSensorsList::slotProcessExited(int exitCode)
                  {
                   const QObjectList *list= &children();
                  
                   if (!list) return;
                  
                   if (process->outputErrors())
                     qWarning("HddTemp Error:\n%s", process->getStdoutData().toAscii().data());
                  
                   QStringList buf = process->getStdoutData().split(QChar('\n'));
                   for(QStringList::Iterator it = buf.begin(); it != buf.end(); ++it ) {
                     for ( QObjectList::ConstIterator olIt = list->begin(); olIt != list->end(); ++olIt ) {
                       Sensor *obj = (Sensor *)(*olIt);
                   
                       QRegExp rx(QString(obj->objectName()) + QString(":\\s+.+:\\s+(\\d+).*C"));
                       if (rx.indexIn((*it)) > -1)
                         obj->setValue(rx.cap(1).toDouble(), Sensor::dgCelsius); 
                     }
                   }
                   delete process;
                   process= 0;
                  }
                  ........................................................
                  
                  G Offline
                  G Offline
                  giusdbg
                  wrote on last edited by
                  #14

                  @giusdbg The sequence of the case is

                  • Timer calls HDSensorsList::updateSensors()
                  • updateSensors() creates a new ProcessExec object (derived from K-QProcess) and asynchronously start an external program.
                  • External process terminates, ProcessExec raises finished event which is connected to HDSensorsList::slotProcessExited.
                  • slotProcessExited does some graphical updates, then deletes the ProcessExec object.
                  • When exiting from slotProcessExited function, occasionally and randomly, a crash occurs.

                  It looks like a race condition that causes a deleted object to be used.

                  JonBJ 1 Reply Last reply
                  0
                  • G giusdbg

                    @giusdbg The sequence of the case is

                    • Timer calls HDSensorsList::updateSensors()
                    • updateSensors() creates a new ProcessExec object (derived from K-QProcess) and asynchronously start an external program.
                    • External process terminates, ProcessExec raises finished event which is connected to HDSensorsList::slotProcessExited.
                    • slotProcessExited does some graphical updates, then deletes the ProcessExec object.
                    • When exiting from slotProcessExited function, occasionally and randomly, a crash occurs.

                    It looks like a race condition that causes a deleted object to be used.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #15

                    @giusdbg said in Debug with QSignalSpy a timer object causing crashes:

                    • External process terminates, ProcessExec raises finished event which is connected to HDSensorsList::slotProcessExited.
                    • slotProcessExited does some graphical updates, then deletes the ProcessExec object.

                    I would not delete process when I am inside a slot attached to a signal received from that process object. Does process->deleteLater() improve behaviour?

                    G 2 Replies Last reply
                    2
                    • JonBJ JonB

                      @giusdbg said in Debug with QSignalSpy a timer object causing crashes:

                      • External process terminates, ProcessExec raises finished event which is connected to HDSensorsList::slotProcessExited.
                      • slotProcessExited does some graphical updates, then deletes the ProcessExec object.

                      I would not delete process when I am inside a slot attached to a signal received from that process object. Does process->deleteLater() improve behaviour?

                      G Offline
                      G Offline
                      giusdbg
                      wrote on last edited by
                      #16

                      @JonB Thanks, probably yes, I'll try deleteLater() .
                      After this modification it is necessary to test for several days, sometimes the crash occurs after ten seconds, sometimes after many hours.

                      P.S. I would have liked to find out what event was involved in the crash stack trace, to have some event debugging capability.
                      (That's why I thought of QSignalSpy.)

                      1 Reply Last reply
                      0
                      • JonBJ JonB

                        @giusdbg said in Debug with QSignalSpy a timer object causing crashes:

                        • External process terminates, ProcessExec raises finished event which is connected to HDSensorsList::slotProcessExited.
                        • slotProcessExited does some graphical updates, then deletes the ProcessExec object.

                        I would not delete process when I am inside a slot attached to a signal received from that process object. Does process->deleteLater() improve behaviour?

                        G Offline
                        G Offline
                        giusdbg
                        wrote on last edited by
                        #17

                        @JonB It looks like the crash is gone, thanks for the help.

                        1 Reply Last reply
                        0
                        • G giusdbg has marked this topic as solved on

                        • Login

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