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 4.0k 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
    6 Jun 2023, 01:01

    @JonB Screenshot_20230606_024927.png

    A Offline
    A Offline
    Axel Spoerl
    Moderators
    wrote on 6 Jun 2023, 05:02 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 6 Jun 2023, 08:48
    1
    • A Axel Spoerl
      6 Jun 2023, 05:02

      @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 6 Jun 2023, 08:48 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?

      J 1 Reply Last reply 6 Jun 2023, 09:49
      0
      • G giusdbg
        6 Jun 2023, 08:48

        @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?

        J Offline
        J Offline
        JonB
        wrote on 6 Jun 2023, 09:49 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 6 Jun 2023, 10:39
        0
        • J JonB
          6 Jun 2023, 09:49

          @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 6 Jun 2023, 10:39 last edited by giusdbg 6 Jun 2023, 11:19
          #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.

          A 1 Reply Last reply 6 Jun 2023, 11:18
          0
          • G giusdbg
            6 Jun 2023, 10:39

            @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.

            A Offline
            A Offline
            Axel Spoerl
            Moderators
            wrote on 6 Jun 2023, 11:18 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 6 Jun 2023, 11:23
            1
            • A Axel Spoerl
              6 Jun 2023, 11:18

              @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 6 Jun 2023, 11:23 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 6 Jun 2023, 14:10
              0
              • G giusdbg
                6 Jun 2023, 11:23

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

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

                G Offline
                G Offline
                giusdbg
                wrote on 6 Jun 2023, 14:10 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 7 Jun 2023, 05:36
                0
                • G giusdbg
                  6 Jun 2023, 14:10

                  @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 7 Jun 2023, 05:36 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.

                  J 1 Reply Last reply 7 Jun 2023, 07:09
                  0
                  • G giusdbg
                    7 Jun 2023, 05:36

                    @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.

                    J Offline
                    J Offline
                    JonB
                    wrote on 7 Jun 2023, 07:09 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 7 Jun 2023, 07:24
                    2
                    • J JonB
                      7 Jun 2023, 07:09

                      @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 7 Jun 2023, 07:24 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
                      • J JonB
                        7 Jun 2023, 07:09

                        @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 8 Jun 2023, 09:25 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 8 Jun 2023, 11:54

                        16/17

                        7 Jun 2023, 07:24

                        • Login

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