Edge case problems



  • I have a project out in user's hands and for the most part it's working well (OS X & Windows) but I'm getting the occasional edge case where the program goes non-responsive (progress bar fills to end and program sits there). If you look at the code below you'll see that I'm using QProcess and a progress bar. Most of the routines in my program are similar, using QProcess to send various commands to an external program (adb, android debug bridge). I can't duplicate these problems and I've tested using Windows XP, Windows 7 and OS X Mav. I thought perhaps resources, so I ran my code under XP with 1Gb of RAM: ran fine w/o issues. Unfortunately, it's all remote, no way I can directly observe.

    Any ideas?

    @
    ui->progressBar->setHidden(false);
    ui->progressBar->setValue(0);

          QTimer *timer = new QTimer(this);
          connect(timer, SIGNAL(timeout()), this, SLOT(TimerEvent()));
          timer->start(tsvalue);
    
    
          QProcess install_apk;
          install_apk.setProcessChannelMode(QProcess::MergedChannels);
          QString cstring = adb + " install -r " + '"'+ fileName+'"';
          install_apk.start(cstring);
    
           while(install_apk.state() != QProcess::NotRunning)
               qApp->processEvents();
    
           command=install_apk.readAll();
           
           ui->progressBar->setHidden(true);
    
           if (command.contains("Success"))
              QMessageBox::information(
                          this,
                         "",
                          "Installed");
              else
              QMessageBox::critical(
                          this,
                          "",
                          "Install failed");
    

    @


  • Moderators

    It's hard to say but a wild guess would be that you're not calling install_apk.waitForStarted(). If the process doesn't "start to start" before you get to the while loop it will be in the NotRunning state, so you'll skip to the readAll() which I don't know what does on the process that didn't start yet.

    In any case I would recommend to rewrite this part into a proper OO manner, where you have a worker object that starts the process and reads output in the slot responding to the finished() signal of the process. You wouldn't have to call processEvents() in a loop, which is always a good indicator of refactoring opportunity.



  • Thanks. I'll give this some thought.



  • If I understand correctly, I'm setting up a slot, "RunProcess". I pass it a value (cstring) then when the signal waitForFinished emits it returns the contents of readAll()?

    @
    QString MainWindow::RunProcess(QString cstring)
    {
    QProcess run_command;
    run_command.setProcessChannelMode(QProcess::MergedChannels);
    run_command.start(cstring);
    run_command.waitForFinished(-1);
    command=run_command.readAll();
    return command;
    }

    void MainWindow::on_sideload_Button_clicked()
    {

    QString cstring = adb + " install -r " + '"'+ fileName+'"';

    connect(QString command, SIGNAL(waitForFinished()), this, SLOT(RunProcess(cstring)));

    }
    @

    The slot RunProcess compiles, but the connect statement fails. Am I on the right track?


  • Moderators

    No, there is no signal waitForFinished. waitForFinished is a blocking method. There is a finished() signal.

    @
    class Foo : public QObject {
    Q_OBJECT
    public:
    Foo() {
    connect(&p, &QProcess::finished, this, &Foo::stuffEnded);
    }
    void doStuff() {
    ...
    p.start();
    }
    void stuffEnded(int exitCode, QProcess::ExitStatus exitStatus) {
    if(exitCode == 0)
    {
    p.readAllStandardOutput();
    ...
    }
    }
    private:
    QProcess p;
    };
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.