Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. QProcess start() freezes GUI with QEventLoop
Forum Updated to NodeBB v4.3 + New Features

QProcess start() freezes GUI with QEventLoop

Scheduled Pinned Locked Moved Solved Mobile and Embedded
6 Posts 2 Posters 1.9k 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.
  • C Offline
    C Offline
    cyrilfr
    wrote on last edited by cyrilfr
    #1

    Hi,

    I'm running a GUI in HTML with QWebEngine and QWebChannel on Embedded Linux. Everything works fine except at some point when I try to run commands with QProcess. The GUI freezes.

    Here is the code causing the GUI to freeze:

    bool enableGsm(bool enable)
    {
        QProcess process;
        QStringList cmd;
        QEventLoop loop;
        connect(&process, SIGNAL(finished(int)), &loop, SLOT(quit()));
    
        cmd << "gsm" << "set_conf" << "enable" << (enable ? "true" : "false");
    
        process.start(cmd.join(' '));
        loop.exec();
    
        if (QString(process.readAllStandardOutput()).contains("OK"))
        {
            cmd.clear();
            cmd << "ifup" << (enable ? GSM_INTERFACE : WLAN_INTERFACE);
    
            process.start(cmd.join(' '));
            loop.exec();
    
            auto info = qInfo();
            info.noquote();
            info << "GSM " << (enable ? "enabled" : "disabled") << ".";
            return true;
        }
    
        return false;
    }
    

    I make this function invokable:

    Q_INVOKABLE bool enableGsm(bool enable);
    

    And run it from JavaScript:

    conf.enableGsm(enable);
    

    The ifup command can be pretty long to run so the GUI freezes for a long time and goes back OK once finished. In other similar cases with a ping command it doesn't freeze.

    jsulmJ 1 Reply Last reply
    0
    • C cyrilfr

      Hi,

      I'm running a GUI in HTML with QWebEngine and QWebChannel on Embedded Linux. Everything works fine except at some point when I try to run commands with QProcess. The GUI freezes.

      Here is the code causing the GUI to freeze:

      bool enableGsm(bool enable)
      {
          QProcess process;
          QStringList cmd;
          QEventLoop loop;
          connect(&process, SIGNAL(finished(int)), &loop, SLOT(quit()));
      
          cmd << "gsm" << "set_conf" << "enable" << (enable ? "true" : "false");
      
          process.start(cmd.join(' '));
          loop.exec();
      
          if (QString(process.readAllStandardOutput()).contains("OK"))
          {
              cmd.clear();
              cmd << "ifup" << (enable ? GSM_INTERFACE : WLAN_INTERFACE);
      
              process.start(cmd.join(' '));
              loop.exec();
      
              auto info = qInfo();
              info.noquote();
              info << "GSM " << (enable ? "enabled" : "disabled") << ".";
              return true;
          }
      
          return false;
      }
      

      I make this function invokable:

      Q_INVOKABLE bool enableGsm(bool enable);
      

      And run it from JavaScript:

      conf.enableGsm(enable);
      

      The ifup command can be pretty long to run so the GUI freezes for a long time and goes back OK once finished. In other similar cases with a ping command it doesn't freeze.

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by jsulm
      #2

      @cyrilfr You're blocking your UI with that event loop not QProcess. Why do you have that event loop?
      You can connect a slot to finished() signal from your QProcess to get notified when it is finished.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      C 1 Reply Last reply
      4
      • C Offline
        C Offline
        cyrilfr
        wrote on last edited by
        #3

        OK, I thought the purpose of QEventLoop was to avoid GUI freeze. I'll try to connect to a JS slot otherwise. Thanks.

        1 Reply Last reply
        0
        • jsulmJ jsulm

          @cyrilfr You're blocking your UI with that event loop not QProcess. Why do you have that event loop?
          You can connect a slot to finished() signal from your QProcess to get notified when it is finished.

          C Offline
          C Offline
          cyrilfr
          wrote on last edited by cyrilfr
          #4

          @jsulm I tried using a slot connected to the readyReadStandardOutput signal but it says:

          {WARNING} QProcess: Destroyed while process ("ifup") is still running.
          

          At the end of the function.

          void enableGsm(bool enable)
          {
              QProcess process;
              QStringList cmd;
          
              cmd << "gsm" << "set_conf" << "enable" << (enable ? "true" : "false");
          
              process.start(cmd.join(' '));
              process.waitForFinished();
          
              if (QString(process.readAllStandardOutput()).contains("OK"))
              {
                  cmd.clear();
                  cmd << "ifup" << (enable ? GSM_INTERFACE : WLAN_INTERFACE);
          
                  connect(&process, &QProcess::readyReadStandardOutput, [this, enable]
                  {
                      auto info = qInfo();
                      info.noquote();
                      info << "GSM " << (enable ? "enabled" : "disabled") << ".";
          
                      emit gsmConfigured(true);
                  });
          
                  process.start(cmd.join(' '));
              }
              else
              {
                  emit gsmConfigured(false);
              }
          }
          
          jsulmJ 1 Reply Last reply
          0
          • C cyrilfr

            @jsulm I tried using a slot connected to the readyReadStandardOutput signal but it says:

            {WARNING} QProcess: Destroyed while process ("ifup") is still running.
            

            At the end of the function.

            void enableGsm(bool enable)
            {
                QProcess process;
                QStringList cmd;
            
                cmd << "gsm" << "set_conf" << "enable" << (enable ? "true" : "false");
            
                process.start(cmd.join(' '));
                process.waitForFinished();
            
                if (QString(process.readAllStandardOutput()).contains("OK"))
                {
                    cmd.clear();
                    cmd << "ifup" << (enable ? GSM_INTERFACE : WLAN_INTERFACE);
            
                    connect(&process, &QProcess::readyReadStandardOutput, [this, enable]
                    {
                        auto info = qInfo();
                        info.noquote();
                        info << "GSM " << (enable ? "enabled" : "disabled") << ".";
            
                        emit gsmConfigured(true);
                    });
            
                    process.start(cmd.join(' '));
                }
                else
                {
                    emit gsmConfigured(false);
                }
            }
            
            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by jsulm
            #5

            @cyrilfr Currently you're allocating QProcess instance on the stack inside your method - it is destroyed as soon as the method finishes. Simply make the QProcess instance member of your class or allocate it on the heap (and delete later when not needed).
            Also, now you're blocking again your UI because you call

            process.waitForFinished();
            

            !
            You should learn how asynchronous programming works, else you will struggle a lot with Qt and other assynchronous frameworks. Basically you have to move everything after process.start(cmd.join(' ')); to your finished() slot.

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            C 1 Reply Last reply
            1
            • jsulmJ jsulm

              @cyrilfr Currently you're allocating QProcess instance on the stack inside your method - it is destroyed as soon as the method finishes. Simply make the QProcess instance member of your class or allocate it on the heap (and delete later when not needed).
              Also, now you're blocking again your UI because you call

              process.waitForFinished();
              

              !
              You should learn how asynchronous programming works, else you will struggle a lot with Qt and other assynchronous frameworks. Basically you have to move everything after process.start(cmd.join(' ')); to your finished() slot.

              C Offline
              C Offline
              cyrilfr
              wrote on last edited by
              #6

              @jsulm Putting the QProcess as a member resolved my issue. I know about waitForFinished() but in this case the command is short enough to run so it doesn't freeze at all.

              Basically you have to move everything after process.start(cmd.join(' ')); to your finished() slot.
              This is what I've done I guess.

              1 Reply Last reply
              1

              • Login

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