From 17318fdd4e711fe68015e4a00de11dc31354885a Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Wed, 25 Jan 2017 12:10:48 +0100 Subject: [PATCH] review: ProcessHandle + minor changes --- src/uvw/process.hpp | 68 +++++++++++++++++++++++++++++++++++---------- src/uvw/tty.hpp | 6 ++-- src/uvw/util.hpp | 4 +++ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/uvw/process.hpp b/src/uvw/process.hpp index 380cc5e2..04949cfc 100644 --- a/src/uvw/process.hpp +++ b/src/uvw/process.hpp @@ -1,9 +1,11 @@ #pragma once +#include #include #include #include +#include #include #include "event.hpp" #include "handle.hpp" @@ -70,7 +72,13 @@ public: using Process = details::UVProcessFlags; using StdIO = details::UVStdIOFlags; - using Handle::Handle; + ProcessHandle(ConstructorAccess ca, std::shared_ptr ref) + : Handle{std::move(ca), std::move(ref)} + { + auto ignore = static_cast(StdIO::IGNORE_STREAM); + auto stdin = uv_stdio_container_t{ignore}; + poFdStdio.push_back(std::move(stdin)); + } /** * @brief Disables inheritance for file descriptors/handles. @@ -130,11 +138,20 @@ public: po.env = env; po.cwd = poCwd.empty() ? nullptr : poCwd.data(); po.flags = poFlags; - po.stdio_count = poStdio.size(); - po.stdio = poStdio.data(); po.uid = poUid; po.gid = poGid; + /** + * See the constructor, poFdStdio[0] is stdin. It must be poStdio[0] by + * convention. From the official documentation: + * + * > The convention is that stdio[0] points to stdin, fd 1 is used + * > for stdout, and fd 2 is stderr. + */ + std::vector poStdio{poFdStdio.size() + poStreamStdio.size()}; + poStdio.insert(poStdio.begin(), poStreamStdio.cbegin(), poStreamStdio.cend()); + poStdio.insert(poStdio.begin(), poFdStdio.cbegin(), poFdStdio.cend()); + invoke(&uv_spawn, parent(), get(), &po); } @@ -206,17 +223,17 @@ public: * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags) * for further details. * - * @param flags A valid set of flags. * @param stream A valid `stdio` handle. + * @param flags A valid set of flags. * @return A reference to this process handle. */ template - ProcessHandle& stdio(Flags flags, StreamHandle &stream) { + ProcessHandle& stdio(StreamHandle &stream, Flags flags) { uv_stdio_container_t container; Flags::Type fgs = flags; container.flags = static_cast(fgs); container.data.stream = get(stream); - poStdio.push_back(std::move(container)); + poStreamStdio.push_back(std::move(container)); return *this; } @@ -232,20 +249,42 @@ public: * * `ProcessHandle::StdIO::READABLE_PIPE` * * `ProcessHandle::StdIO::WRITABLE_PIPE` * + * Default file descriptors are: + * * `uvw::StdIN` for `stdin` + * * `uvw::StdOUT` for `stdout` + * * `uvw::StdERR` for `stderr` + * * See the official * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags) * for further details. * - * @param flags A valid set of flags. * @param fd A valid file descriptor. + * @param flags A valid set of flags. * @return A reference to this process handle. */ - ProcessHandle& stdio(Flags flags, FileHandle fd) { - uv_stdio_container_t container; - Flags::Type fgs = flags; - container.flags = static_cast(fgs); - container.data.fd = fd; - poStdio.push_back(std::move(container)); + ProcessHandle& stdio(FileHandle fd, Flags flags) { + auto fgs = static_cast(Flags::Type{flags}); + + auto actual = FileHandle::Type{fd}; + + if(actual == FileHandle::Type{StdIN}) { + poFdStdio[0].flags = fgs; + } else { + auto it = std::find_if(poFdStdio.begin(), poFdStdio.end(), [actual](auto &&container){ + return container.data.fd == actual; + }); + + if(it == poFdStdio.cend()) { + uv_stdio_container_t container; + container.flags = fgs; + container.data.fd = actual; + poFdStdio.push_back(std::move(container)); + } else { + it->flags = fgs; + it->data.fd = actual; + } + } + return *this; } @@ -272,7 +311,8 @@ public: private: std::string poCwd; Flags poFlags; - std::vector poStdio; + std::vector poFdStdio; + std::vector poStreamStdio; Uid poUid; Gid poGid; }; diff --git a/src/uvw/tty.hpp b/src/uvw/tty.hpp index 834f7826..aa3b969e 100644 --- a/src/uvw/tty.hpp +++ b/src/uvw/tty.hpp @@ -41,9 +41,9 @@ enum class UVTTYModeT: std::underlying_type_t { * To create a `TTYHandle` through a `Loop`, arguments follow: * * * A valid FileHandle. Usually the file descriptor will be: - * * `0` = `stdin` - * * `1` = `stdout` - * * `2` = `stderr` + * * `uvw::StdIN` or `0` for `stdin` + * * `uvw::StdOUT` or `1` for `stdout` + * * `uvw::StdERR` or `2` for `stderr` * * A boolean value that specifies the plan on calling `read()` with this * stream. Remember that `stdin` is readable, `stdout` is not. * diff --git a/src/uvw/util.hpp b/src/uvw/util.hpp index e1e7eb35..f5310041 100644 --- a/src/uvw/util.hpp +++ b/src/uvw/util.hpp @@ -186,6 +186,10 @@ using FileHandle = details::UVTypeWrapper; using OSSocketHandle = details::UVTypeWrapper; using OSFileDescriptor = details::UVTypeWrapper; +constexpr FileHandle StdIN{0}; /*!< Placeholder for stdin descriptor. */ +constexpr FileHandle StdOUT{1}; /*!< Placeholder for stdout descriptor. */ +constexpr FileHandle StdERR{2}; /*!< Placeholder for stderr descriptor. */ + using TimeSpec = uv_timespec_t; using Stat = uv_stat_t; using Uid = uv_uid_t;