forked from OctaForge/libostd
hide platform-specific data from subprocess
This commit is contained in:
parent
31c3602839
commit
ea7f4062b7
|
@ -103,11 +103,9 @@ struct OSTD_EXPORT subprocess {
|
||||||
|
|
||||||
subprocess(subprocess &&i):
|
subprocess(subprocess &&i):
|
||||||
use_in(i.use_in), use_out(i.use_out), use_err(i.use_err),
|
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)),
|
in(std::move(i.in)), out(std::move(i.out)), err(std::move(i.err))
|
||||||
pid(i.pid), errno_fd(i.errno_fd)
|
|
||||||
{
|
{
|
||||||
i.pid = -1;
|
move_data(i);
|
||||||
i.errno_fd = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subprocess &operator=(subprocess &&i) {
|
subprocess &operator=(subprocess &&i) {
|
||||||
|
@ -123,8 +121,7 @@ struct OSTD_EXPORT subprocess {
|
||||||
swap(in, i.in);
|
swap(in, i.in);
|
||||||
swap(out, i.out);
|
swap(out, i.out);
|
||||||
swap(err, i.err);
|
swap(err, i.err);
|
||||||
swap(pid, i.pid);
|
swap_data(i);
|
||||||
swap(errno_fd, i.errno_fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~subprocess();
|
~subprocess();
|
||||||
|
@ -177,8 +174,11 @@ private:
|
||||||
);
|
);
|
||||||
|
|
||||||
void reset();
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -128,6 +128,10 @@ OSTD_EXPORT void split_args_impl(
|
||||||
} /* namespace detail */
|
} /* namespace detail */
|
||||||
|
|
||||||
#ifndef OSTD_PLATFORM_WIN32
|
#ifndef OSTD_PLATFORM_WIN32
|
||||||
|
struct data {
|
||||||
|
int pid = -1, errno_fd = -1;
|
||||||
|
};
|
||||||
|
|
||||||
struct pipe {
|
struct pipe {
|
||||||
int fd[2] = { -1, -1 };
|
int fd[2] = { -1, -1 };
|
||||||
|
|
||||||
|
@ -197,6 +201,9 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
}
|
}
|
||||||
argp[args.size()] = nullptr;
|
argp[args.size()] = nullptr;
|
||||||
|
|
||||||
|
p_current = ::new (reinterpret_cast<void *>(&p_data)) data{};
|
||||||
|
data *pd = static_cast<data *>(p_current);
|
||||||
|
|
||||||
/* fd_errno used to detect if exec failed */
|
/* fd_errno used to detect if exec failed */
|
||||||
pipe fd_errno, fd_stdin, fd_stdout, fd_stderr;
|
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.close(true);
|
||||||
fd_stderr.fdopen(err, false);
|
fd_stderr.fdopen(err, false);
|
||||||
}
|
}
|
||||||
pid = int(cpid);
|
pd->pid = int(cpid);
|
||||||
errno_fd = std::exchange(fd_errno[1], -1);
|
pd->errno_fd = std::exchange(fd_errno[1], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OSTD_EXPORT void subprocess::reset() {
|
OSTD_EXPORT void subprocess::reset() {
|
||||||
pid = -1;
|
if (!p_current) {
|
||||||
if (errno_fd >= 0) {
|
return;
|
||||||
::close(std::exchange(errno_fd, -1));
|
}
|
||||||
|
data *pd = static_cast<data *>(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<data *>(i.p_current);
|
||||||
|
if (!od) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p_current = ::new (reinterpret_cast<void *>(&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<data *>(p_current), *static_cast<data *>(i.p_current)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OSTD_EXPORT int subprocess::close() {
|
OSTD_EXPORT int subprocess::close() {
|
||||||
if (pid < 0) {
|
if (!p_current) {
|
||||||
reset();
|
|
||||||
throw process_error{ECHILD, std::generic_category()};
|
throw process_error{ECHILD, std::generic_category()};
|
||||||
}
|
}
|
||||||
|
data *pd = static_cast<data *>(p_current);
|
||||||
int retc = 0;
|
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();
|
reset();
|
||||||
throw process_error{errno, std::generic_category()};
|
throw process_error{errno, std::generic_category()};
|
||||||
}
|
}
|
||||||
if (retc) {
|
if (retc) {
|
||||||
int eno;
|
int eno;
|
||||||
auto r = read(errno_fd, &eno, sizeof(int));
|
auto r = read(pd->errno_fd, &eno, sizeof(int));
|
||||||
reset();
|
reset();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throw process_error{errno, std::generic_category()};
|
throw process_error{errno, std::generic_category()};
|
||||||
|
@ -295,14 +327,8 @@ OSTD_EXPORT int subprocess::close() {
|
||||||
throw process_error{eno, std::generic_category()};
|
throw process_error{eno, std::generic_category()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retc;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSTD_EXPORT subprocess::~subprocess() {
|
|
||||||
try {
|
|
||||||
close();
|
|
||||||
} catch (process_error const &) {}
|
|
||||||
reset();
|
reset();
|
||||||
|
return retc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* OSTD_PLATFORM_WIN32 */
|
#else /* OSTD_PLATFORM_WIN32 */
|
||||||
|
@ -317,10 +343,16 @@ OSTD_EXPORT int subprocess::close() {
|
||||||
throw process_error{ECHILD, std::generic_category()};
|
throw process_error{ECHILD, std::generic_category()};
|
||||||
}
|
}
|
||||||
|
|
||||||
OSTD_EXPORT subprocess::~subprocess() {
|
OSTD_EXPORT void subprocess::reset() {
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
OSTD_EXPORT subprocess::~subprocess() {
|
||||||
|
try {
|
||||||
|
close();
|
||||||
|
} catch (process_error const &) {}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ostd */
|
} /* namespace ostd */
|
||||||
|
|
Loading…
Reference in a new issue