diff options
author | Rafael Roquetto <rafael.roquetto.qnx@kdab.com> | 2014-07-29 17:10:02 -0300 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2015-01-23 19:13:30 +0100 |
commit | bc4b1d7efe6e4a3b830f96d87b9c5c40adfa1bf1 (patch) | |
tree | 925871d254227862e7da9da4c8f5800394d73b04 | |
parent | 75a2c81b0041df4ca59178cf52d9e5a8815f3524 (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.cpp | 40 |
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); |