Reputation: 50338
#include <cstdio>
#include <QtCore/QProcess>
int main (int argc, char** argv) {
// if we remove 3 following lines, the problem described below doesn't exists!!
QProcess process;
process.start ("asdqwe"); // doesn't matter what we try to execute here.
process.waitForStarted (1000);
while (true) {
char buf[100];
if (scanf ("%s", buf) == EOF) { // it looks like stdin is closed!
printf("FAIL\n");
return 1;
}
printf ("%s\n", buf);
}
return 0;
}
This code is just a snippet to show the problem. In the full application I need read/write communication with process.
I compile it with:
g++ -o out ./main.cpp -I /usr/include/qt4/ -lQtCore
And execute it from bash command line in terminal.
Why this program sometimes prints FAIL and sometimes will stay in loop?
Edit: This is not question about scan/printf. The same problem is if I use iostreams + string. This question is about interaction of QProcess with file descriptors of parent process.
Upvotes: 2
Views: 697
Reputation: 50338
#include <cstdio>
#include <QtCore/QProcess>
int main (int argc, char** argv) {
// if we remove 3 following lines, the problem described below doesn't exists!!
QProcess process;
process.start ("asdqwe"); // doesn't matter what we try to execute here.
process.waitForStarted (1000);
while (true) {
char buf[100];
if (scanf ("%s", buf) == EOF) { // it looks like stdin is closed!
if (errno == EINTR) {
errno = 0;
continue;
}
printf("FAIL\n");
return 1;
}
printf ("%s\n", buf);
}
return 0;
}
I really use streams, I had to use
cin.clear();
errno = 0;
Upvotes: 0
Reputation: 99384
Your scanf
was interrupted by SIGCHLD signal that was caught when child process terminated. In this case EOF
is also returned.
QProcess
stuff does set up signal handler for SIGCHLD (check sources): (4.5.3 here)
Q_GLOBAL_STATIC(QProcessManager, processManager)
QProcessManager::QProcessManager()
{
#if defined (QPROCESS_DEBUG)
qDebug() << "QProcessManager::QProcessManager()";
#endif
// initialize the dead child pipe and make it non-blocking.
// (pipe and fcntl skipped - P. Shved.)
// set up the SIGCHLD handler, which writes a single byte to the dead
// child pipe every time a child dies.
struct sigaction oldAction;
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = qt_sa_sigchld_handler;
action.sa_flags = SA_NOCLDSTOP;
::sigaction(SIGCHLD, &action, &oldAction);
if (oldAction.sa_handler != qt_sa_sigchld_handler)
qt_sa_old_sigchld_handler = oldAction.sa_handler;
}
Upvotes: 3