summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Roquetto <rafael.roquetto.qnx@kdab.com>2014-07-29 17:10:02 -0300
committerThiago Macieira <thiago.macieira@intel.com>2015-01-23 19:13:30 +0100
commitbc4b1d7efe6e4a3b830f96d87b9c5c40adfa1bf1 (patch)
tree925871d254227862e7da9da4c8f5800394d73b04
parent75a2c81b0041df4ca59178cf52d9e5a8815f3524 (diff)
QNX: QProcess workaround for the stdin pipe
Due to a bug in the internal implementation of posix_spawnp on QNX, all file descriptors with a value lower than the maximum file descriptor specified in the file_actions structure are duplicated by default, ignoring the FD_CLOEXEC flag. This includes all file descriptors that we are not working with. So we add those file descriptors that have the FD_CLOEXEC flag to the file_actions structure as close actions. Change-Id: I316bc334addb46a4b84c199a69e9bd291ca706c5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qprocess_unix.cpp40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index d626607dfa..63e052094f 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -593,24 +593,58 @@ pid_t QProcessPrivate::spawnChild(pid_t *ppid, const char *workingDir, char **ar
posix_spawn_file_actions_t file_actions;
posix_spawn_file_actions_init(&file_actions);
+# ifdef Q_OS_QNX
+ static const bool OS_QNX = true;
+# else
+ static const bool OS_QNX = false;
+#endif
+
+ int fdmax = -1;
+
if (processChannelMode == QProcess::MergedChannels) {
// managed stderr == stdout
posix_spawn_file_actions_adddup2(&file_actions, stdoutChannel.pipe[1], STDERR_FILENO);
+
+ if (OS_QNX)
+ fdmax = qMax(fdmax, stdoutChannel.pipe[1]);
} else if (processChannelMode != QProcess::ForwardedChannels && processChannelMode != QProcess::ForwardedErrorChannel) {
// managed stderr
posix_spawn_file_actions_adddup2(&file_actions, stderrChannel.pipe[1], STDERR_FILENO);
- posix_spawn_file_actions_addclose(&file_actions, stderrChannel.pipe[1]);
+
+ if (OS_QNX)
+ fdmax = qMax(fdmax, stderrChannel.pipe[1]);
+ else
+ posix_spawn_file_actions_addclose(&file_actions, stderrChannel.pipe[1]);
+
}
if (processChannelMode != QProcess::ForwardedChannels && processChannelMode != QProcess::ForwardedOutputChannel) {
// managed stdout
posix_spawn_file_actions_adddup2(&file_actions, stdoutChannel.pipe[1], STDOUT_FILENO);
- posix_spawn_file_actions_addclose(&file_actions, stdoutChannel.pipe[1]);
+
+ if (OS_QNX)
+ fdmax = qMax(fdmax, stdoutChannel.pipe[1]);
+ else
+ posix_spawn_file_actions_addclose(&file_actions, stdoutChannel.pipe[1]);
+
}
if (inputChannelMode == QProcess::ManagedInputChannel) {
posix_spawn_file_actions_adddup2(&file_actions, stdinChannel.pipe[0], STDIN_FILENO);
- posix_spawn_file_actions_addclose(&file_actions, stdinChannel.pipe[0]);
+
+ if (OS_QNX)
+ fdmax = qMax(fdmax, stdinChannel.pipe[0]);
+ else
+ posix_spawn_file_actions_addclose(&file_actions, stdinChannel.pipe[0]);
+ }
+
+ // Workaround: QNX's spawn implementation will actually dup all FD values
+ // LESS than fdmax - regardless of the FD_CLOEEXEC flag. So we need to add
+ // those to the list of files to close, otherwise dup will fail when some
+ // other thread closes the FD.
+ for (int i = 3; i <= fdmax; i++) {
+ if (::fcntl(i, F_GETFD) & FD_CLOEXEC)
+ posix_spawn_file_actions_addclose(&file_actions, i);
}
int retval = doSpawn(ppid, &file_actions, argv, envp, workingDir, false);