QProcess::readAllStandardOutput gives flaky outputs - qt

I am trying to create a GUI in Qt4 for my tcl based tool. In order to populate widgets I need to execute some tcl commands. I read about QProcess and I am invoking tcl scripts using QProcess and then grabbing their output from stdout.
Suppose I execute 3 commands in tcl then when I query stdout I believe I should see 3 outputs corresponding to each of the three commands, however this is not happening consistently. Behavior is flaky.
As you can see in the main.cpp I am executing multiple commands using runTclCommand() function and in the end executing getData() function to read stdout.
main.cpp:
#include <QApplication>
#include <QProcess>
#include <QDebug>
#include "Tclsh.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QByteArray out;
Tclsh *tcl = new Tclsh;
tcl->startTclsh();
tcl->runTclCommand("set ::tcl_interactive 1\n");
tcl->runTclCommand("set a 23\n");
tcl->runTclCommand("puts $a\n");
tcl->runTclCommand("set a 40\n");
tcl->runTclCommand("puts $a\n");
// out = idl->getData();
out = tcl->getData();
}
Tclsh.cpp:
#include <QProcessEnvironment>
#include <QProcess>
#include <QDebug>
#include "Tclsh.h"
void Tclsh::startTclsh() {
QString program = "/usr/bin/tclsh8.4";
this->setProcessChannelMode(QProcess::MergedChannels);
this->start(program);
if ( !this->waitForStarted()) {
qDebug()<<"ERROR Starting tclsh";
}
return;
}
void Tclsh::runTclCommand(const char *cmd) {
qDebug()<<"CMD:"<<cmd;
this->write(cmd);
if (!this->waitForBytesWritten()) {
qDebug()<<"Error in writing data";
}
}
QByteArray Tclsh::getData() {
if (!this->waitForReadyRead()) {
qDebug()<<"Error in reading stdout: Ready read signal is not emitted";
}
QByteArray data = this->readAllStandardOutput();
qDebug()<<"DATA:"<<data;
return data;
}
However, sometime I get the following output:
CMD: set ::tcl_interactive 1
CMD: set a 23
CMD: puts $a
CMD: set a 40
CMD: puts $a
DATA: "1
% 23
% 23
% "
And sometimes this:
CMD: set ::tcl_interactive 1
CMD: set a 23
CMD: puts $a
CMD: set a 40
CMD: puts $a
DATA: "1
"
I do not understand why this is happening. I would really appreciate if someone can point me to the error in my approach here.
Thanks,
Newbie
Edit: After some more research, here are my thoughts
According to Qt manual, readyRead signal will be emitted whenever new data is available (as specified by #Frank Osterfeld also, thanks!). It will not wait for complete output data to be available (which is justified since it does not know when will that happen). Hence my approach is not good. What I can do is something like this:
start the process -> wait for process to finish -> read stdout
This will ensure that flaky behavior does not arise as process is already finished when I am reading hence no new data can come.
However, in this proposed approach I am not clear about one thing: Does stdout is specific to a process? I mean can it happen that process which was supposed to read stdout output from process1, can get other stdout data from some other process which happen to write stdout at the same time as process1?
Thanks,
Newbie

I am closing this question. Reading from a channel more than once does not seem to a be a good idea. Instead what I do now is write what I want to write in one go --> close the channel for writing --> then read it back. In that way I get consistent output.

Related

set-UID privieged programs

I have 2 question:
Consider the situation where Alice runs a owned Set-UID program
by Bob. The program wants to read the file contained in / etc / data, readable by
Alice, but by no one else. Can this program access the file?
Consider the situation where a process wants to access a file for reading;
the effective user ID of the process is 3000 and the real user ID is 4000. If the file is readable
for user ID 4000, but not for user ID 3000, this process can access the
file?
These are really the same question, and the answer in both cases is no, unless the program uses setresuid to change its effective UID to its real UID, or it uses setfsuid (Linux-specific) to change its filesystem UID to its real UID. But the program would have to be designed for this scenario; an ordinary program that never manipulates its UID/GID and just accesses files will fail the permission check.
Here is a concrete example of how to answer your part 1 question in code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
static void flipuids(void) {
uid_t r = getuid();
uid_t e = geteuid();
if (setreuid(e, r)) {
perror("failed to flip");
exit(1);
}
}
int main(int argc, char *argv[]) {
printf("euid=%d uid=%d\n", geteuid(), getuid());
flipuids();
printf("euid=%d uid=%d\n", geteuid(), getuid());
FILE *file = fopen("/tmp/alices", "r");
if (file == NULL) {
perror("no reads");
exit(1);
}
flipuids();
printf("euid=%d uid=%d\n", geteuid(), getuid());
fclose(file);
}
If you chmod +s ./uidaccess to make sure that the program has these permissions:
$ ls -l ./uidaccess
-rwsr-sr-x 1 bob bob 17008 Apr 18 09:34 uidaccess
Once the program is run by alice, it is an example of a process operating as described in your part 2 question.

How to do a non-blocking read on a non-socket fd

Is there a way to do a single read() in non-blocking mode on a pipe/terminal/etc, the way I can do it on a socket with recv(MSG_DONTWAIT)?
The reason I need that is because I cannot find any guarantee that a read() on a file-descriptor returned as ready for reading by select() or poll() will not block.
I know can make the file descriptor non-blocking with fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) but this will change the mode on that file descriptor globally, not just in the calling thread/process. For example:
% perl -MFcntl=F_SETFL,F_GETFL,O_NONBLOCK -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) | O_NONBLOCK; select undef, undef, undef, undef'
^Z # put it in the background
% cat
cat: -: Resource temporarily unavailable
This will also make the fd non blocking for both reading and writing, which may confuse the hell out of another process doing the opposite on the same fd, as in:
non_blocking_read | filter | blocking_write
One way I think of is to save the file status flags on starting up and SIGCONT, and restore them on exiting and on SIGTSTP (just the way it's done with the termios settings), but this is very limited, race-prone, and will leave a mess behind in the case where the program exited abnormally.
Putting a save/restore with fcntl() before/after each read() also feels ugly and dumb, and may have other issues too. The same with an ioctl(FIONREAD) just before the read (which I'm not even sure it will work reliably with any fd; assurances in that direction will be welcome, though).
I would be happy even with system specific (eg. linux or bsd-only) solutions.
For reference, here is a discussion about fixing it in linux; the idea didn't seem to get anywhere, though.
A Linux only solution would be to reopen the file descriptor via
"/dev/stdin"|"/dev/tty"|"/dev/fd/$fd".
C example:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd;
char buf[8];
int flags;
if(0>(fd=open("/dev/stdin", O_RDONLY))) return 1;
if(0>(flags = fcntl(fd,F_GETFL))) return 1;
if(0>(flags = fcntl(fd,F_SETFL,flags|O_NONBLOCK))) return 1;
sleep(3);
puts("reading");
ssize_t nr = read(fd, buf, sizeof(buf));
printf("read=%zd\n", nr);
return 0;
}
Unlike a duplicated file descriptor, a reopened filedescriptor will have independent file status flags.

Can I use QCommandLineParser to determine GUI mode or CLI mode?

One of the programs that I work with has two modes that it can run in: GUI (Graphical User Interface) mode or CLI (Command-Line Interface) mode. We determine which mode to use via a command line argument (i.e., if "--cli" is passed, it will use CLI mode).
The type of QApplication that is instantiated depends on which mode is used: QApplication should be used for GUI mode, and QCoreApplication should be used for CLI mode, because the GUI parts of Qt should not be instantiated for CLI mode (since CLI mode does not use or need them).
I can do that via code similar to the following:
std::unique_ptr<QCoreApplication> app =
(cliMode) ? std::make_unique<QCoreApplication>(argc, argv)
: std::make_unique<QApplication>(argc, argv);
// Do some other stuff...
return app->exec();
Since I am already using Qt, it makes sense to use QCommandLineParser to parse my arguments. After parsing the arguments, I want to analyze them to determine whether we should run in GUI mode or CLI mode. However, it has been becoming increasingly difficult to do so.
The first problem I noticed was the following on Linux (this did not happen in older versions of Qt5, but it does happen in the newer versions):
$ ./myQtApplication --help
QCoreApplication::arguments: Please instantiate the QApplication object first
Segmentation fault (core dumped)
Okay: so I can no longer run the --help command without already having a QApplication object instantiated. I temporarily fixed this by manually parsing the arguments to see whether or not --help is an argument. If it is, go ahead and instantiated the QCoreApplication, parse the arguments, and then exit.
But then I started getting a cryptic error on Mac OS X. When I would run the executable on OS X directly, it would run without any issues. But if I tried to double-click on the .app file or type in the terminal $ open myQtApplication.app, I would get this cryptic error:
LSOpenURLsWithRole() failed with error -10810 for the file ./myQtApplication.app
Since it is a rather cryptic error, it took me a long time to figure out that this error was being caused by the QCommandLineParser being used before having a QApplication object instantiated.
To fix this, I am now doing the following:
Manually parse the arguments at the beginning of the main() function to determine whether or not --cli was passed.
Instantiate a QApplication object based on the results of #1.
Run QCommandLineParser to process the rest of the arguments.
This is not a very clean way to do this because I now have two argument parsers: one to determine if --cli was passed, and the rest for the other arguments.
Is there a much better, or "proper", way to do this?
I guess the main question is: can I use QCommandLineParser to determine whether to instantiate a QCoreApplication object or a QApplication object?
Of course you can use the parser - as long as QCoreApplication already present. If the --cli option is absent, you will switch to a QApplication. Recall that you have full control over the lifetime of the application object.
This works under Qt 4.8 and 5.11 on both Windows and OS X:
// https://github.com/KubaO/stackoverflown/tree/master/questions/app-cli-gui-switch-52649458
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#endif
struct Options {
bool cli;
};
static Options parseOptionsQt4() {
Options opts = {};
for (auto arg : QCoreApplication::arguments().mid(1)) {
if (arg == "--cli")
opts.cli = true;
else
qFatal("Unknown option %s", arg.toLocal8Bit().constData());
}
return opts;
}
static Options parseOptions() {
if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) return parseOptionsQt4();
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Options opts = {};
QCommandLineParser parser;
QCommandLineOption cliOption("cli", "Start in command line mode.");
parser.addOption(cliOption);
parser.process(*qApp);
opts.cli = parser.isSet(cliOption);
return opts;
#endif
}
int main(int argc, char *argv[]) {
QScopedPointer<QCoreApplication> app(new QCoreApplication(argc, argv));
auto options = parseOptions();
if (options.cli) {
qDebug() << "cli";
} else {
qDebug() << "gui";
app.reset();
app.reset(new QApplication(argc, argv));
}
if (qobject_cast<QApplication *>(qApp))
QMessageBox::information(nullptr, "Hello", "Hello, World!");
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
return app->exec();
}

How can I run multiple threads inside of a given MPI process?

I understand that a single MPI job Launches many processes which could be run on multiple nodes.
How do I run multiple threads inside of a given MPI process using MPI_THREAD_MULTIPLE?
I was unable to find enough information in relation to the topic.
Assuming your using OpenMP to run multiple threads
You will write the OpenMP code as you would do with out the MPI. (this statement is over simplified)
When the MPI comes you need to consider how your process will communicate. MPI is not sending messages to individual threads but individual process. For that reason MPI provides four modes of interaction with threads.
MPI_THREAD_SINGLE: Provides only one thread
MPI_THREAD_FUNNELED: Can provide many threads, but only the master thread can make MPI calls. The master thread is the one who call MPI_Init...
MPI_THREAD_SERIALIZED: Can provide many threads, but only one can make MPI calls at a time.
MPI_THREAD_MULTIPE: Can provide many threads, and all of them can make MPI call at any time.
You need to specify the mode you want at MPI_Init, which becomes:
MPI_Init_thread(&argc, &argv, HERE_PUT_THE_MODE_YOU_NEED, PROVIDED_MODE)
Ex:
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPE, &provided)
At the provided field the MPI_Init_thread returns the provided mode. Make sure that you got a mode that your code can cope with it.
Also, avoid the use of MPI_Probe and MPI_IProbe, because they are not thread save. You should use MPI_Mprobe and MPI_Improbe.
Here is a simple 'hello world' example as #ab2050 asked:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include "mpi.h"
int main(int argc, char *argv[]) {
int provided;
int rank;
MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided);
if (provided != MPI_THREAD_FUNNELED) {
fprintf(stderr, "Warning MPI did not provide MPI_THREAD_FUNNELED\n");
}
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
#pragma omp parallel default(none), \
shared(rank), \
shared(ompi_mpi_comm_world), \
shared(ompi_mpi_int), \
shared(ompi_mpi_char)
{
printf("Hello from thread %d at rank %d parallel region\n",
omp_get_thread_num(), rank);
#pragma omp master
{
char helloWorld[12];
if (rank == 0) {
strcpy(helloWorld, "Hello World");
MPI_Send(helloWorld, 12, MPI_CHAR, 1, 0, MPI_COMM_WORLD);
printf("Rank %d send: %s\n", rank, helloWorld);
}
else {
MPI_Recv(helloWorld, 12, MPI_CHAR, 0, 0, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
printf("Rank %d received: %s\n", rank, helloWorld);
}
}
}
MPI_Finalize();
return 0;
}
You have to run this code on two process. Because 'MPI_THREAD_FUNNELED' is selected only the master thread makes MPI calls.
The following variables are specified at OpenMP data scoping place
because is needed by gcc version 6.1.1. Older versions like 4.8 do not require to declare them.
ompi_mpi_comm_world
ompi_mpi_char

QProcess problems, output of process

I am trying to figure out the use of QProcess. I looked at Qt doc with no luck.
http://doc.qt.io/qt-4.8/qprocess.html
EXAMPLES OF PROBLEM.
Example 1: Code bellow works.
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QProcess cmd;
cmd.start("cmd");
if (!cmd.waitForStarted()) {
return false;
}
cmd.waitForReadyRead();
QByteArray result = cmd.readAll();
//qout << result.data() << endl; //console junk captured, doesn't show.
//My test command
cmd.write("echo hello");
cmd.write("\n");
//Capture my result
cmd.waitForReadyRead();
//This is my command shown by cmd, I don't show it, capture & discard it.
result = cmd.readLine();
//Read result of my command ("hello") and the rest of output like cur dir.
result = cmd.readAll();
qout << result.data();
qout << "\n\n---End, bye----" << endl;
return a.exec();
}
The output of the above code is
hello
F:\Dev_Qt\expControllingExtConsoleApps-build-desktop>
---End, bye----
The problem is that if I try to use ipconfig or 7zip in this fashion via Qprocess and cmd console, I am unable to see any output from ipconfig or 7zip. I don't know if anything is even done, if something is done then why can't I see the output? Code below illustrates.
Example 2: Does not work. Can't use ipconfig.
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QString>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QProcess cmd2;
cmd2.setWorkingDirectory("C:/Program Files/7-Zip"); //not needed in this example.
cmd2.setReadChannel(QProcess::StandardOutput);
cmd2.setProcessChannelMode(QProcess::MergedChannels);
cmd2.start("cmd");
if (!cmd2.waitForStarted())
{
qout << "Error: Could not start!" << endl;
return false;
}
cmd2.waitForReadyRead();
QByteArray result = cmd2.readAll();
qout << result.data() << endl; //Console version info, etc.
//My command
cmd2.write("ipconfig");
cmd2.write("\n");
//Capture output of ipconfig command
//DOES NOT WORK!!
cmd2.waitForReadyRead();
while (! cmd2.atEnd())
{
result = cmd2.readLine();
qout << result;
result.clear();
}
qout << endl;
qout << "\n\n---end----" << endl;
return a.exec();
}
Output is below, it is missing the ipconfig connection information result. No output from ipconfig is captured at all.
Microsoft Windows XP [Version
5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.
C:\Program Files\7-Zip> ipconfig
---end----
Should have been more like this (with ipconfig result).
Microsoft Windows XP [Version
5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and
Settings\noname>ipconfig
Windows IP Configuration
Ethernet adapter Local Area
Connection:
Connection-specific DNS Suffix . :
IP Address. . . . . . . . . . . . : 192.172.148.135
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.172.148.177
C:\Documents and Settings\noname>
Obviously the output should should have been a little diff than above but the Connection info which is the output of "ipconfig" should have been captured. In the same way if I try to use 7zip via cmd console... I can not see/capture any output of 7zip. So my question is how can I use command line apps like ipconfig and 7zip via QProcess and cmd console and see the result of the output of these applications?
Example 3: 7zip does not work
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QProcess cmd2;
cmd2.setWorkingDirectory("C:/Program Files/7-Zip");
cmd2.setReadChannel(QProcess::StandardOutput);
cmd2.setProcessChannelMode(QProcess::MergedChannels);
cmd2.start("cmd");
if (!cmd2.waitForStarted()) {
return false;
}
//My Command
cmd2.write("7z.exe");
cmd2.write("\n");
//Capture output of ipconfig command
cmd2.waitForReadyRead();
QByteArray result;
while (! cmd2.atEnd()) {
result = cmd2.readLine();
qout << result;
result.clear();
}
qout << endl;
qout << "\n\n---end----" << endl;
return a.exec();
}
Output below. Does not show anything from 7zip.
Microsoft Windows XP [Version
5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.
C:\Program Files\7-Zip>7z.exe
---end----
Output is expected to be along the lines of...
Microsoft Windows XP [Version
5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\noname>cd
C:\Program Files\7-Zip
C:\Program Files\7-Zip>7z.exe
7-Zip 9.15 beta Copyright (c)
1999-2010 Igor Pavlov 2010-06-20
Usage: 7z [...]
<archive_name> [<file_names>...]
[<#listfiles...>]
a: Add files to archive
b: Benchmark d: Delete files from
archive e: Extract files from
archive (without using directory
names) l: List contents of archive
t: Test integrity of archive u:
Update files to archive x: eXtract
files with full paths
-ai[r[-|0]]{#listfile|!wildcard}: Include archives
-ax[r[-|0]]{#listfile|!wildcard}: eXclude archives -bd: Disable
percentage indicator
-i[r[-|0]]{#listfile|!wildcard}: Include filenames -m{Parameters}:
set compression Method
-o{Directory}: set Output directory -p{Password}: set Password -r[-|0]: Recurse subdirectories -scs{UTF-8 |
WIN | DOS}: set charset for list files
-sfx[{name}]: Create SFX archive -si[{name}]: read data from stdin -slt: show technical information for l (List) command -so: write data to
stdout -ssc[-]: set sensitive case
mode -ssw: compress shared files
-t{Type}: Set type of archive -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]:
Update options -v{Size}[b|k|m|g]:
Create volumes -w[{path}]: assign
Work directory. Empty path means a
temporary directory
-x[r[-|0]]]{#listfile|!wildcard}: eXclude filenames -y: assume Yes on
all queries
C:\Program Files\7-Zip>
eI see one big problem.
Under windows you issue a commend pressing the Enter key. Writing
cmd.write("command");
cmd.write("\n");
just isn't enough you have to write
cmd.write("command");
cmd.write("\n\r");
Notice the trailing \r. Try this, it should work better, and by better I mean 7zip. I don't know if you'll get ipconfig to work properly.
Good luck and best regards
D
EDIT
Here is a working solution:
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QString>
#include <QtCore/QTextStream>
// Not clean, but fast
QProcess *g_process = NULL;
// Needed as a signal catcher
class ProcOut : public QObject
{
Q_OBJECT
public:
ProcOut (QObject *parent = NULL);
virtual ~ProcOut() {};
public slots:
void readyRead();
void finished();
};
ProcOut::ProcOut (QObject *parent /* = NULL */):
QObject(parent)
{}
void
ProcOut::readyRead()
{
if (!g_process)
return;
QTextStream out(stdout);
out << g_process->readAllStandardOutput() << endl;
}
void
ProcOut::finished()
{
QCoreApplication::exit (0);
}
int main (int argc, char **argv)
{
QCoreApplication *app = new QCoreApplication (argc, argv);
ProcOut *procOut = new ProcOut();
g_process = new QProcess();
QObject::connect (g_process, SIGNAL(readyReadStandardOutput()),
procOut, SLOT(readyRead()));
QObject::connect (g_process, SIGNAL(finished (int, QProcess::ExitStatus)),
procOut, SLOT(finished()));
g_process->start (QLatin1String ("cmd"));
g_process->waitForStarted();
g_process->write ("ipconfig\n\r");
// Or cmd won't quit
g_process->write ("exit\n\r");
int result = app->exec();
// Allright, process finished.
delete procOut;
procOut = NULL;
delete g_process;
g_process = NULL;
delete app;
app = NULL;
// Lets us see the results
system ("pause");
return result;
}
#include "main.moc"
Hope that helps. It worked everytime on my machine.
Even though Dariusz Scharsig already provided a solution to the problem, I would like to point out what I believe to be the actual problem(s) which can be solved using the signal slot mechanism.
Problem 1. The condition in your while loop is based on bool QProcess::atEnd () const which is according to QProcess Documentation states:
Reimplemented from QIODevice::atEnd().
Returns true if the process is
not running, and no more data is available for reading; otherwise
returns false.
But if you looking the documentation for QIODevice::atEnd(), it states:
Returns true if the current read and write position is at the end of
the device (i.e. there is no more data available for reading on the
device); otherwise returns false.
For some devices, atEnd() can return
true even though there is more data to read. This special case only
applies to devices that generate data in direct response to you
calling read() (e.g., /dev or /proc files on Unix and Mac OS X, or
console input / stdin on all platforms).
Solution 1. Change the while loop condition to check the state of your process: while(cmd2.state()!=QProcess::NotRunning){.
Problem 2. You use cmd2.waitForReadyRead(); outside of the loop. Perhaps some data is ready for reading now and when you finished reading, some more gets made available:
you read the commands you just wrote : ipconfig\n
ipconfig takes some time to start up and send text to the console. But by then you have already exited your loop because atEnd() gave true even though your process is still running.
Solution 2. place the waitForReadyRead() inside your loop.
Consequence 2. waitForReadyRead() will tell you when there is data available, which could be more than one Line, so you should consequently also change the cmd2.ReadLine() to cmd2.ReadAll().
Problem 3. As documented in QProcess::closeWriteChannel()
Closing the write channel is necessary for programs that read input
data until the channel has been closed.
Solution 3. One of the following options should work when finished writing your inputs
End the process: cmd2.write("exit\n");
close the Writechannel: cmd2.closeWriteChannel();
Working code:
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QString>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QByteArray result;
QProcess cmd2;
cmd2.setReadChannel(QProcess::StandardOutput);
cmd2.setProcessChannelMode(QProcess::MergedChannels);
cmd2.start("cmd");
if (!cmd2.waitForStarted()){
qout << "Error: Could not start!" << endl;
return 0;
}
cmd2.write("ipconfig\n");
cmd2.closeWriteChannel(); //done Writing
while(cmd2.state()!=QProcess::NotRunning){
cmd2.waitForReadyRead();
result = cmd2.readAll();
qout << result;
}
qout << endl << "---end----" << endl;
return a.exec();
}
I wrote this answer just to explain the way I understand your problem and found a solution but would like to emphasize that the Preferable Solution is to use the Signal/Slot Mechanism as presented by Dariusz.

Resources