summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@digia.com>2013-09-03 22:06:26 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-05 21:17:44 +0200
commit50a8a5e7959ca315e812413661a76576b7c3bbb8 (patch)
treefadd591bb515323705ee372ea069b58471eedb07
parentfba0a307914772b286e8f315e0d1dec5ce7935f8 (diff)
add QProcess::InputChannelMode
this enables forwarding standard input from the parent process. Change-Id: I7ee72b9842acc96320d4da693b95dd15d9a7b4d4 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
-rw-r--r--src/corelib/io/qprocess.cpp53
-rw-r--r--src/corelib/io/qprocess.h6
-rw-r--r--src/corelib/io/qprocess_p.h1
-rw-r--r--src/corelib/io/qprocess_unix.cpp15
-rw-r--r--src/corelib/io/qprocess_win.cpp10
-rw-r--r--tests/auto/corelib/io/qprocess/testForwarding/main.cpp9
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp17
7 files changed, 94 insertions, 17 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 27a8bce3fe..7f4d7f0313 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -608,8 +608,8 @@ void QProcessPrivate::Channel::clear()
/*!
\enum QProcess::ProcessChannelMode
- This enum describes the process channel modes of QProcess. Pass
- one of these values to setProcessChannelMode() to set the
+ This enum describes the process output channel modes of QProcess.
+ Pass one of these values to setProcessChannelMode() to set the
current read channel mode.
\value SeparateChannels QProcess manages the output of the
@@ -652,6 +652,26 @@ void QProcessPrivate::Channel::clear()
*/
/*!
+ \enum QProcess::InputChannelMode
+ \since 5.2
+
+ This enum describes the process input channel modes of QProcess.
+ Pass one of these values to setInputChannelMode() to set the
+ current write channel mode.
+
+ \value ManagedInputChannel QProcess manages the input of the running
+ process. This is the default input channel mode of QProcess.
+
+ \value ForwardedInputChannel QProcess forwards the input of the main
+ process onto the running process. The child process reads its standard
+ input from the same source as the main process.
+ Note that the main process must not try to read its standard input
+ while the child process is running.
+
+ \sa setInputChannelMode()
+*/
+
+/*!
\enum QProcess::ProcessError
This enum describes the different types of errors that are
@@ -779,6 +799,7 @@ QProcessPrivate::QProcessPrivate()
{
processChannel = QProcess::StandardOutput;
processChannelMode = QProcess::SeparateChannels;
+ inputChannelMode = QProcess::ManagedInputChannel;
processError = QProcess::UnknownError;
processState = QProcess::NotRunning;
pid = 0;
@@ -1244,6 +1265,34 @@ void QProcess::setProcessChannelMode(ProcessChannelMode mode)
}
/*!
+ \since 5.2
+
+ Returns the channel mode of the QProcess standard input channel.
+
+ \sa setInputChannelMode(), InputChannelMode
+*/
+QProcess::InputChannelMode QProcess::inputChannelMode() const
+{
+ Q_D(const QProcess);
+ return d->inputChannelMode;
+}
+
+/*!
+ \since 5.2
+
+ Sets the channel mode of the QProcess standard intput
+ channel to the \a mode specified.
+ This mode will be used the next time start() is called.
+
+ \sa inputChannelMode(), InputChannelMode
+*/
+void QProcess::setInputChannelMode(InputChannelMode mode)
+{
+ Q_D(QProcess);
+ d->inputChannelMode = mode;
+}
+
+/*!
Returns the current read channel of the QProcess.
\sa setReadChannel()
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 0984d501fd..c0b3ab945e 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -128,6 +128,10 @@ public:
ForwardedOutputChannel,
ForwardedErrorChannel
};
+ enum InputChannelMode {
+ ManagedInputChannel,
+ ForwardedInputChannel
+ };
enum ExitStatus {
NormalExit,
CrashExit
@@ -151,6 +155,8 @@ public:
void setReadChannelMode(ProcessChannelMode mode);
ProcessChannelMode processChannelMode() const;
void setProcessChannelMode(ProcessChannelMode mode);
+ InputChannelMode inputChannelMode() const;
+ void setInputChannelMode(InputChannelMode mode);
ProcessChannel readChannel() const;
void setReadChannel(ProcessChannel channel);
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index e96cb42f94..219bdf8200 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -302,6 +302,7 @@ public:
QProcess::ProcessChannel processChannel;
QProcess::ProcessChannelMode processChannelMode;
+ QProcess::InputChannelMode inputChannelMode;
QProcess::ProcessError processError;
QProcess::ProcessState processState;
QString workingDirectory;
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 0e0ead5897..9868ea624a 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -807,29 +807,29 @@ pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **en
? i : SPAWN_FDCLOSED;
}
+ if (inputChannelMode == QProcess::ManagedInputChannel)
+ fd_map[0] = stdinChannel.pipe[0];
+ else
+ fd_map[0] = QT_FILENO(stdin);
+
switch (processChannelMode) {
case QProcess::ForwardedChannels:
- fd_map[0] = stdinChannel.pipe[0];
fd_map[1] = QT_FILENO(stdout);
fd_map[2] = QT_FILENO(stderr);
break;
case QProcess::ForwardedOutputChannel:
- fd_map[0] = stdinChannel.pipe[0];
fd_map[1] = QT_FILENO(stdout);
fd_map[2] = stderrChannel.pipe[1];
break;
case QProcess::ForwardedErrorChannel:
- fd_map[0] = stdinChannel.pipe[0];
fd_map[1] = stdoutChannel.pipe[1];
fd_map[2] = QT_FILENO(stderr);
break;
case QProcess::MergedChannels:
- fd_map[0] = stdinChannel.pipe[0];
fd_map[1] = stdoutChannel.pipe[1];
fd_map[2] = stdoutChannel.pipe[1];
break;
case QProcess::SeparateChannels:
- fd_map[0] = stdinChannel.pipe[0];
fd_map[1] = stdoutChannel.pipe[1];
fd_map[2] = stderrChannel.pipe[1];
break;
@@ -855,8 +855,9 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
Q_Q(QProcess);
- // copy the stdin socket (without closing on exec)
- qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0);
+ // copy the stdin socket if asked to (without closing on exec)
+ if (inputChannelMode != QProcess::ForwardedInputChannel)
+ qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0);
// copy the stdout and stderr if asked to
if (processChannelMode != QProcess::ForwardedChannels) {
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index f545386f56..291ea319ec 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -156,7 +156,15 @@ bool QProcessPrivate::createChannel(Channel &channel)
if (channel.type == Channel::Normal) {
// we're piping this channel to our own process
if (&channel == &stdinChannel) {
- qt_create_pipe(channel.pipe, true);
+ if (inputChannelMode != QProcess::ForwardedInputChannel) {
+ qt_create_pipe(channel.pipe, true);
+ } else {
+ channel.pipe[1] = INVALID_Q_PIPE;
+ HANDLE hStdReadChannel = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE hCurrentProcess = GetCurrentProcess();
+ DuplicateHandle(hCurrentProcess, hStdReadChannel, hCurrentProcess,
+ &channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS);
+ }
} else {
QWindowsPipeReader *pipeReader = 0;
if (&channel == &stdoutChannel) {
diff --git a/tests/auto/corelib/io/qprocess/testForwarding/main.cpp b/tests/auto/corelib/io/qprocess/testForwarding/main.cpp
index deff2b95ad..42394f6414 100644
--- a/tests/auto/corelib/io/qprocess/testForwarding/main.cpp
+++ b/tests/auto/corelib/io/qprocess/testForwarding/main.cpp
@@ -48,7 +48,7 @@ int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
- if (argc < 2)
+ if (argc < 3)
return 13;
#ifndef QT_NO_PROCESS
@@ -59,12 +59,17 @@ int main(int argc, char **argv)
if (process.processChannelMode() != mode)
return 1;
+ QProcess::InputChannelMode inmode = (QProcess::InputChannelMode)atoi(argv[2]);
+ process.setInputChannelMode(inmode);
+ if (process.inputChannelMode() != inmode)
+ return 11;
+
process.start("testProcessEcho2/testProcessEcho2");
if (!process.waitForStarted(5000))
return 2;
- if (process.write("forwarded") != 9)
+ if (inmode == QProcess::ManagedInputChannel && process.write("forwarded") != 9)
return 3;
process.closeWriteChannel();
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index e03c1fb75e..d248f022ed 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -1094,33 +1094,40 @@ void tst_QProcess::mergedChannels()
void tst_QProcess::forwardedChannels_data()
{
QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("inmode");
QTest::addColumn<QByteArray>("outdata");
QTest::addColumn<QByteArray>("errdata");
- QTest::newRow("separate") << int(QProcess::SeparateChannels)
+ QTest::newRow("separate") << int(QProcess::SeparateChannels) << int(QProcess::ManagedInputChannel)
<< QByteArray() << QByteArray();
- QTest::newRow("forwarded") << int(QProcess::ForwardedChannels)
+ QTest::newRow("forwarded") << int(QProcess::ForwardedChannels) << int(QProcess::ManagedInputChannel)
<< QByteArray("forwarded") << QByteArray("forwarded");
- QTest::newRow("stdout") << int(QProcess::ForwardedOutputChannel)
+ QTest::newRow("stdout") << int(QProcess::ForwardedOutputChannel) << int(QProcess::ManagedInputChannel)
<< QByteArray("forwarded") << QByteArray();
- QTest::newRow("stderr") << int(QProcess::ForwardedErrorChannel)
+ QTest::newRow("stderr") << int(QProcess::ForwardedErrorChannel) << int(QProcess::ManagedInputChannel)
<< QByteArray() << QByteArray("forwarded");
+ QTest::newRow("fwdinput") << int(QProcess::ForwardedErrorChannel) << int(QProcess::ForwardedInputChannel)
+ << QByteArray() << QByteArray("input");
}
void tst_QProcess::forwardedChannels()
{
QFETCH(int, mode);
+ QFETCH(int, inmode);
QFETCH(QByteArray, outdata);
QFETCH(QByteArray, errdata);
QProcess process;
- process.start("testForwarding/testForwarding", QStringList() << QString::number(mode));
+ process.start("testForwarding/testForwarding", QStringList() << QString::number(mode) << QString::number(inmode));
QVERIFY(process.waitForStarted(5000));
+ QCOMPARE(process.write("input"), 5);
+ process.closeWriteChannel();
QVERIFY(process.waitForFinished(5000));
const char *err;
switch (process.exitCode()) {
case 0: err = "ok"; break;
case 1: err = "processChannelMode is wrong"; break;
+ case 11: err = "inputChannelMode is wrong"; break;
case 2: err = "failed to start"; break;
case 3: err = "failed to write"; break;
case 4: err = "did not finish"; break;