review: ProcessHandle + minor changes

This commit is contained in:
Michele Caini 2017-01-25 12:10:48 +01:00
parent 438886b425
commit 17318fdd4e
3 changed files with 61 additions and 17 deletions

View File

@ -1,9 +1,11 @@
#pragma once
#include <algorithm>
#include <utility>
#include <memory>
#include <string>
#include <vector>
#include <uv.h>
#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<Loop> ref)
: Handle{std::move(ca), std::move(ref)}
{
auto ignore = static_cast<uv_stdio_flags>(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<uv_stdio_container_t> 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<typename T, typename U>
ProcessHandle& stdio(Flags<StdIO> flags, StreamHandle<T, U> &stream) {
ProcessHandle& stdio(StreamHandle<T, U> &stream, Flags<StdIO> flags) {
uv_stdio_container_t container;
Flags<StdIO>::Type fgs = flags;
container.flags = static_cast<uv_stdio_flags>(fgs);
container.data.stream = get<uv_stream_t>(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<StdIO> flags, FileHandle fd) {
uv_stdio_container_t container;
Flags<StdIO>::Type fgs = flags;
container.flags = static_cast<uv_stdio_flags>(fgs);
container.data.fd = fd;
poStdio.push_back(std::move(container));
ProcessHandle& stdio(FileHandle fd, Flags<StdIO> flags) {
auto fgs = static_cast<uv_stdio_flags>(Flags<StdIO>::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<Process> poFlags;
std::vector<uv_stdio_container_t> poStdio;
std::vector<uv_stdio_container_t> poFdStdio;
std::vector<uv_stdio_container_t> poStreamStdio;
Uid poUid;
Gid poGid;
};

View File

@ -41,9 +41,9 @@ enum class UVTTYModeT: std::underlying_type_t<uv_tty_mode_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.
*

View File

@ -186,6 +186,10 @@ using FileHandle = details::UVTypeWrapper<uv_file>;
using OSSocketHandle = details::UVTypeWrapper<uv_os_sock_t>;
using OSFileDescriptor = details::UVTypeWrapper<uv_os_fd_t>;
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;