From ea7f4062b795b42ce16becdf5f1bc1e7d90a1e02 Mon Sep 17 00:00:00 2001 From: q66 Date: Mon, 8 May 2017 20:32:36 +0200 Subject: [PATCH] hide platform-specific data from subprocess --- ostd/process.hh | 14 +++++----- src/process.cc | 68 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/ostd/process.hh b/ostd/process.hh index a2683af..f707c65 100644 --- a/ostd/process.hh +++ b/ostd/process.hh @@ -103,11 +103,9 @@ struct OSTD_EXPORT subprocess { subprocess(subprocess &&i): use_in(i.use_in), use_out(i.use_out), use_err(i.use_err), - in(std::move(i.in)), out(std::move(i.out)), err(std::move(i.err)), - pid(i.pid), errno_fd(i.errno_fd) + in(std::move(i.in)), out(std::move(i.out)), err(std::move(i.err)) { - i.pid = -1; - i.errno_fd = -1; + move_data(i); } subprocess &operator=(subprocess &&i) { @@ -123,8 +121,7 @@ struct OSTD_EXPORT subprocess { swap(in, i.in); swap(out, i.out); swap(err, i.err); - swap(pid, i.pid); - swap(errno_fd, i.errno_fd); + swap_data(i); } ~subprocess(); @@ -177,8 +174,11 @@ private: ); void reset(); + void move_data(subprocess &i); + void swap_data(subprocess &i); - int pid = -1, errno_fd = -1; + std::aligned_storage_t<2 * sizeof(void *)> p_data; + void *p_current = nullptr; }; /** @} */ diff --git a/src/process.cc b/src/process.cc index 89b24a8..c6d4612 100644 --- a/src/process.cc +++ b/src/process.cc @@ -128,6 +128,10 @@ OSTD_EXPORT void split_args_impl( } /* namespace detail */ #ifndef OSTD_PLATFORM_WIN32 +struct data { + int pid = -1, errno_fd = -1; +}; + struct pipe { int fd[2] = { -1, -1 }; @@ -197,6 +201,9 @@ OSTD_EXPORT void subprocess::open_impl( } argp[args.size()] = nullptr; + p_current = ::new (reinterpret_cast(&p_data)) data{}; + data *pd = static_cast(p_current); + /* fd_errno used to detect if exec failed */ pipe fd_errno, fd_stdin, fd_stdout, fd_stderr; @@ -263,31 +270,56 @@ OSTD_EXPORT void subprocess::open_impl( fd_stderr.close(true); fd_stderr.fdopen(err, false); } - pid = int(cpid); - errno_fd = std::exchange(fd_errno[1], -1); + pd->pid = int(cpid); + pd->errno_fd = std::exchange(fd_errno[1], -1); } } OSTD_EXPORT void subprocess::reset() { - pid = -1; - if (errno_fd >= 0) { - ::close(std::exchange(errno_fd, -1)); + if (!p_current) { + return; + } + data *pd = static_cast(p_current); + if (pd->errno_fd >= 0) { + ::close(pd->errno_fd); + } + p_current = nullptr; +} + +OSTD_EXPORT void subprocess::move_data(subprocess &i) { + data *od = static_cast(i.p_current); + if (!od) { + return; + } + p_current = ::new (reinterpret_cast(&p_data)) data{*od}; + i.p_current = nullptr; +} + +OSTD_EXPORT void subprocess::swap_data(subprocess &i) { + if (!p_current) { + move_data(i); + } else if (!i.p_current) { + i.move_data(*this); + } else { + std::swap( + *static_cast(p_current), *static_cast(i.p_current) + ); } } OSTD_EXPORT int subprocess::close() { - if (pid < 0) { - reset(); + if (!p_current) { throw process_error{ECHILD, std::generic_category()}; } + data *pd = static_cast(p_current); int retc = 0; - if (pid_t wp; (wp = waitpid(pid, &retc, 0)) < 0) { + if (pid_t wp; (wp = waitpid(pd->pid, &retc, 0)) < 0) { reset(); throw process_error{errno, std::generic_category()}; } if (retc) { int eno; - auto r = read(errno_fd, &eno, sizeof(int)); + auto r = read(pd->errno_fd, &eno, sizeof(int)); reset(); if (r < 0) { throw process_error{errno, std::generic_category()}; @@ -295,14 +327,8 @@ OSTD_EXPORT int subprocess::close() { throw process_error{eno, std::generic_category()}; } } - return retc; -} - -OSTD_EXPORT subprocess::~subprocess() { - try { - close(); - } catch (process_error const &) {} reset(); + return retc; } #else /* OSTD_PLATFORM_WIN32 */ @@ -317,10 +343,16 @@ OSTD_EXPORT int subprocess::close() { throw process_error{ECHILD, std::generic_category()}; } -OSTD_EXPORT subprocess::~subprocess() { - return; +OSTD_EXPORT void subprocess::reset() { } #endif +OSTD_EXPORT subprocess::~subprocess() { + try { + close(); + } catch (process_error const &) {} + reset(); +} + } /* namespace ostd */