PDA

View Full Version : why can't QProcess read all output?



Raul
6th June 2010, 03:13
hi guys!
I'm using QProcess start a program,but I'm come across a problem.the problem is when I read the QProcess,it doesn't read all of the output.eg,actually,the output should be two lines,but it shows only one line.what's wrong with it?If someone can help me?thanks!

wysota
6th June 2010, 07:23
There are two possibilities:
1. the other line doesn't end with a \n so it wasn't flushed by the system into the output stream
2. the other line was sent to stderr and not stdout

Raul
6th June 2010, 08:37
There are two possibilities:
1. the other line doesn't end with a \n so it wasn't flushed by the system into the output stream
2. the other line was sent to stderr and not stdout

I have knew that the second line end with a \n.and it should be the second possibility,but,before I start the program,I set the process like this: inprocess.setReadChannelMode(QProcess::MergedChann els);
and in the connect,I write like this: connect(&inprocess,SIGNAL(readyReadStandardOutput()),this,S LOT(iupdateTextEdit()));
connect(&inprocess,SIGNAL(readyReadStandardError()),this,SL OT(iupdateTextEdit()));
the following show the iupdateTextEdit() fuction
void mainWindow::iupdateTextEdit()
{
QByteArray newData=inprocess.readAllStandardOutput();
QString text=textEdit->toPlainText()+QString::fromLocal8Bit(newData);
textEdit->setPlainText(text);
}
even so,it can't show the second line in the textEdit.

wysota
6th June 2010, 08:51
Did you try simply readAll()?

Zlatomir
6th June 2010, 08:54
Disclaimer: I didn't use this... so i might be wrong, but
as far as i know the '\n' line end doesn't flush the stream, try to use std::endl to finish the line.

Raul
6th June 2010, 09:06
Did you try simply readAll()?

it doesn't work too.

Raul
6th June 2010, 09:17
Disclaimer: I didn't use this... so i might be wrong, but
as far as i know the '\n' line end doesn't flush the stream, try to use std::endl to finish the line.

the program that i want to call was wrote in C not C++.

Zlatomir
6th June 2010, 09:35
In C you can use:


printf(...);
fflush(stdout);

to flush the stdout buffer

Raul
6th June 2010, 09:47
In C you can use:


printf(...);
fflush(stdout);

to flush the stdout buffer
if like the following ?
void mainWindow::iupdateTextEdit()
{
QByteArray newData=inprocess.readAllStandardOutput();
QString text=textEdit->toPlainText()+QString::fromLocal8Bit(newData);
textEdit->setPlainText(text);
fflush(stdout);
}

Zlatomir
6th June 2010, 09:49
No, don't use that in Qt.

Use that in your C application (if you have the source of the C application)

squidge
6th June 2010, 09:52
If you run your C program from a dos command line, do you get all output?

Raul
6th June 2010, 09:57
No, don't use that in Qt.

Use that in your C application (if you have the source of the C application)

unfortunately,i haven't the soures of the C application.

Raul
6th June 2010, 10:03
If you run your C program from a dos command line, do you get all output?

If i set the Konsole to super Konsole(su -) ,i can get all output.but if i set it to "/bin/bash",it can't .

wysota
6th June 2010, 10:06
Disclaimer: I didn't use this... so i might be wrong, but
as far as i know the '\n' line end doesn't flush the stream, try to use std::endl to finish the line.

Flushing the stream is done by the runtime (or even the operating system), not by the application hence there is no difference between \n and std::endl. And I'm sure \n causes the stream flush, at least in those systems that I know of.

Raul
6th June 2010, 10:37
hi guys!
I'm using QProcess start a program,but I'm come across a problem.the problem is when I read the QProcess,it doesn't read all of the output.eg,actually,the output should be two lines,but it shows only one line.what's wrong with it?If someone can help me?thanks!

to my suprise,it sometimes can read the second line.

Zlatomir
6th June 2010, 10:46
@Wysota: You are right, the actual flush is "done" by the OS, but "when" is done can be controlled from your code, and the new-line character '\n' doesn't "force" the OS to flush the output stream, while the endl does.

@Raul: your problem is within the C application
i don't think that you can force the stream to flush from QProcess (i might be wrong) maybe you can wait for the C application to finnish (that must cause a flush) and then see what you have in that byte-array (again i don't know if QProcess still "capture" the flush if it is closing the other process)

squidge
6th June 2010, 11:05
If i set the Konsole to super Konsole(su -) ,i can get all output.but if i set it to "/bin/bash",it can't .

Then it seems like you can't get the same behaviour from your Qt app without first requesting su?

wysota
6th June 2010, 11:46
@Wysota: You are right, the actual flush is "done" by the OS, but "when" is done can be controlled from your code, and the new-line character '\n' doesn't "force" the OS to flush the output stream, while the endl does.
I don't know if this is the case in all basic operating systems but at least in Unices the default buffering for streams is "line buffering", so \n has to force a flush. Anyway take a look at any decent C application and check if every printf() is followed by fflush.


i don't think that you can force the stream to flush from QProcess (i might be wrong)
You are not wrong. What one could do is to use stddup, disable buffering of the newly created stream and set that stream as stdout of the newly created process (of course you need to spawn it yourself using proper native means). At least in Unices :)

Anyway the "problem" is obviously in behaviour of the slave program.

Zlatomir
6th June 2010, 12:12
@Wysota: I didn't said you are wrong, and you are right about line-buffer in *nix, but this isn't a behavior that you can assume it's true (especially if you want multi-platform)

Anyway take a look at any decent C application and check if every printf() is followed by fflush.
Correct again, it is highly not recommended to force flush on every printf()/cout, because the OS "usually" does a good job and flush the buffer whenever necessary, but this isn't a standard cross-platform "thing" (in some situations you can have different behaviors on same platform), so in some cases like the one we are talking wright now it is (or should be) necessary to "force" the flush.

Raul
6th June 2010, 12:21
Then it seems like you can't get the same behaviour from your Qt app without first requesting su?

I just use QProcess start the program.and read the process.I didn't know how to request su first.if you can tell me how to request su first.

wysota
6th June 2010, 12:39
@Wysota: I didn't said you are wrong, and you are right about line-buffer in *nix, but this isn't a behavior that you can assume it's true (especially if you want multi-platform)
Can you point a platform that doesn't perform a flush on newline?

squidge
6th June 2010, 13:35
I just use QProcess start the program.and read the process.I didn't know how to request su first.if you can tell me how to request su first.

Check out PAM.


Can you point a platform that doesn't perform a flush on newline?

What would also be interesting is that if you open a file as binary, you don't (or at least, I would expect you didn't) get flushing on newline. Do you get fliushing on endl even though the file is binary? I know using endl on a binary file is a bit strange, but it would be interesting to find out. Unless of course endl on a binary file causes a run time error?

Zlatomir
6th June 2010, 13:45
The OS might flush the stream with new line or might not, we can't know for sure, it might look that in 1000 cases flushes the stream and in one case, when we assume it does... the OS make us a surprise... (i saw some people surprised by this issue)

I was talking from the C/C++ programmer point of view (http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.7), for us there is no guarantee that the OS will flush on new line (\n), but in case the programmer isn't "happy" with the OS flushes, he can do it when he want it.

Raul
6th June 2010, 14:10
[QUOTE=fatjuicymole;146411]Check out PAM.


what the "PAM" reffers to?

squidge
6th June 2010, 14:58
http://en.wikipedia.org/wiki/Pluggable_Authentication_Modules

Raul
6th June 2010, 19:17
Then it seems like you can't get the same behaviour from your Qt app without first requesting su?

I think my problem occurs without first requesting su.and i have studied the PAM.but i can't solve my problem yet,the main reason is that i don't know how to request su first:confused:.

squidge
6th June 2010, 20:27
Well, you can always give root access to your program permanently, if you don't want to request it whilst running:

chown root your_app
chmod a+xs your_app

Raul
6th June 2010, 20:46
Well, you can always give root access to your program permanently, if you don't want to request it whilst running:

chown root your_app
chmod a+xs your_app

the result is the same as before.

ChrisW67
6th June 2010, 23:10
I have knew that the second line end with a \n.and it should be the second possibility,but,before I start the program,I set the process like this:
inprocess.setReadChannelMode(QProcess::MergedChann els);and in the connect, I write like this:
connect(&inprocess,SIGNAL(readyReadStandardOutput()),this,S LOT(iupdateTextEdit()));
connect(&inprocess,SIGNAL(readyReadStandardError()),this,SL OT(iupdateTextEdit())); the following show the iupdateTextEdit() fuction

void mainWindow::iupdateTextEdit()
{
QByteArray newData=inprocess.readAllStandardOutput();
QString text=textEdit->toPlainText()+QString::fromLocal8Bit(newData);
textEdit->setPlainText(text);
} even so,it can't show the second line in the textEdit.

We cannot see where, but you are allocating "inprocess" on the stack from the look of this. Are you sure that inprocess is not going out-of-scope at some inconvenient point in time? This might explain the "sometime works" behaviour.

Raul
7th June 2010, 01:29
We cannot see where, but you are allocating "inprocess" on the stack from the look of this. Are you sure that inprocess is not going out-of-scope at some inconvenient point in time? This might explain the "sometime works" behaviour.

I'm not sure.but in Qt,it almost declare a QProcess object .and hardly ever use "new" .what's more,the output only has two lines if it output all results. so i think it isn't like what you say.

ChrisW67
7th June 2010, 07:04
The amount of output you are expecting is irrelevant if the QProcess instance is being destroyed before you want it to be. It's also irrelevant how someone else chooses to create QProcess because it is your code with the problem, not theirs. The first example in the QProcess docs uses the heap for a long-running process, and the second uses a local (stack) variable to run a short-lived process entirely entirely within the same scope.

wysota
7th June 2010, 08:06
What would also be interesting is that if you open a file as binary, you don't (or at least, I would expect you didn't) get flushing on newline. Do you get fliushing on endl even though the file is binary? I know using endl on a binary file is a bit strange, but it would be interesting to find out. Unless of course endl on a binary file causes a run time error?
I would expect a binary stream to be buffered as well. Remember TCP is a binary stream and it is flushed on newline (there are no "modes" for creating a socket).

marc_sturm
15th June 2013, 12:17
If anyone is still interested, here is a possible workaround for the buffer problem:
https://sites.google.com/site/marcsturmspages/qt/qt-workaround-for-the-leaky-qprocess-output-channel