Results 1 to 3 of 3

Thread: Standard error and standard output from QProcess in wrong order

  1. #1
    Join Date
    May 2008
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11

    Question Standard error and standard output from QProcess in wrong order

    I'm trying to write an editor for the ruby programming language using Qt 4. This editor should be able to run a ruby script written by the user and display the output and error messages from the script in a QListView, using a different color for the latter. To do this, I use a QProcess. I connect the readyReadStandardError and readyReadStandardOutput signals from the process with two slots which set the read channel respectively to StandardError and StandardOutput, read the content of the channel and display them.

    Having written this code, I tried running a ruby script which, for 10 times, writes a string to standard error and one to standard output. The result should have been this:

    warning 0
    message 0
    warning 1
    message 1
    ...
    warning 9
    message 9


    where the warnings are the text written to standard error and the messages are the text written to standard output. Instead, what I got is this:


    warning 0
    warning 1
    ...
    warning 9
    message 0
    message 1
    ...
    message 9


    Besides, the slots connected to the readyStandardError and readyStandardOutput are called only once, while I expected each of them to be called ten times (one for each message). Does anyone know what I'm doing wrong or how to achieve the result I want?

    Here's a simplified version of the application. It consists of a simple QPushButton which launches the ruby script and writes the output to the terminal.

    This is the header file for the MyApp class, which contains the QProcess:
    Qt Code:
    1. #ifndef MYAPP_H
    2. #define MYAPP_H
    3.  
    4. #include <QApplication>
    5. #include <QProcess>
    6.  
    7. class MyApp: public QApplication{
    8.  
    9. Q_OBJECT
    10.  
    11. public:
    12.  
    13. MyApp(int argc, char ** argv);
    14. ~MyApp();
    15.  
    16. public slots:
    17. void displayOutputMsg();
    18. void displayErrorMsg();
    19. void runRuby();
    20.  
    21. private:
    22. QProcess * m_proc;
    23. };
    24.  
    25. #endif
    To copy to clipboard, switch view to plain text mode 
    and here's the implementation:
    Qt Code:
    1. #include "app.h"
    2. #include <iostream>
    3. #include <string>
    4. #include <QStringList>
    5.  
    6. MyApp::MyApp(int argc, char ** argv): QApplication(argc, argv), m_proc(new QProcess(this)){
    7. connect(m_proc, SIGNAL(readyReadStandardOutput()),this, SLOT(displayOutputMsg()));
    8. connect(m_proc, SIGNAL(readyReadStandardError()),this, SLOT(displayErrorMsg()));
    9. }
    10.  
    11. MyApp::~MyApp(){}
    12.  
    13. void MyApp::displayOutputMsg(){
    14. m_proc->setReadChannel(QProcess::StandardOutput);
    15. QByteArray msg = m_proc->read(1000);
    16. std::cout << "Output: "<< (msg.data())<<"\n";
    17. }
    18.  
    19. void MyApp::displayErrorMsg(){
    20. m_proc->setReadChannel(QProcess::StandardError);
    21. QByteArray msg = m_proc->read(1000);
    22. std::cout << "Error: "<< (msg.data())<<"\n";
    23. }
    24.  
    25. void MyApp::runRuby(){
    26. args << "-w" << "/home/stefano/documenti/scripts/prova.rb";
    27. m_proc->start("ruby", args);
    28. }
    To copy to clipboard, switch view to plain text mode 

    This is the main.cpp file:
    Qt Code:
    1. #include "app.h"
    2. #include <QPushButton>
    3. #include <QWidget>
    4. #include <QLayout>
    5.  
    6. int main(int argc, char ** argv){
    7. MyApp * app = new MyApp(argc, argv);
    8. QWidget * w = new QWidget;
    9. QLayout * l = new QHBoxLayout(w);
    10. QPushButton * ruby = new QPushButton("Run &ruby", w);
    11. l->addWidget(ruby);
    12. // QPushButton * python = new QPushButton("Run &python", w);
    13. // l->addWidget(python);
    14. app->connect( ruby, SIGNAL(clicked()), SLOT(runRuby()));
    15. // app->connect( python, SIGNAL(clicked()), SLOT(runPython()));
    16. w->show();
    17. app->exec();
    18. }
    To copy to clipboard, switch view to plain text mode 

    Thanks in advance
    Stefano

  2. #2
    Join Date
    May 2008
    Posts
    155
    Thanked 15 Times in 13 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Standard error and standard output from QProcess in wrong order

    That's what you see is probably indeed what the Ruby application produces. I have no idea how Ruby works, but for "usual" C programs stdout and stderr are typically not connected to each other, and stdout is typically buffered whereas stderr is not. So getting all stderr before the stdout buffer is flushed is not uncommon, also merging "packets" is not.

    So to get what you want to you need either to flush after each output operation or to (a) un-buffer stderr and (b) synchronize stderr and stdout, both in the Ruby application.

  3. #3
    Join Date
    May 2008
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Standard error and standard output from QProcess in wrong order

    Thanks for your answer. Since I'm writing a ruby editor, the ruby application will be written by the user, not by me, so I can't change it. At any rate, I tried executing my test ruby script from other editors (kdevelop, scite, netbeans) and they give the same output mine gives, so I guess there's nothing I can do about it.
    Stefano

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.