From 4f9221f3d43295b53200abdfd17ee55c189667cf Mon Sep 17 00:00:00 2001 From: Hudd Date: Fri, 22 Mar 2024 14:58:33 +0400 Subject: [PATCH] io/posix: implement wait() and run() --- io/include/aw/io/posix/process.h | 46 +++++++++++++++++++++++++++----- io/include/aw/io/process.h | 5 +++- io/include/aw/io/win32/process.h | 2 +- io/posix/process.c++ | 36 ++++++++++++++----------- io/tests/process.c++ | 3 ++- 5 files changed, 67 insertions(+), 25 deletions(-) diff --git a/io/include/aw/io/posix/process.h b/io/include/aw/io/posix/process.h index e07ccdee..51c3773f 100644 --- a/io/include/aw/io/posix/process.h +++ b/io/include/aw/io/posix/process.h @@ -19,29 +19,63 @@ constexpr auto invalid_process_handle = process_handle(-1L ); * Spawn a child process with specified \a path and argument list \a argv. * Argument list must end with `nullptr`. */ -AW_IO_EXP process_handle spawn(const char* path, aw::array_ref argv, std::error_code& ec) noexcept; +AW_IO_EXP process_handle spawn(const char* path, aw::array_view argv, std::error_code& ec) noexcept; /*! * Spawn a child process with specified argument list \a argv. `argv[0]` is used as path. */ -AW_IO_EXP process_handle spawn(aw::array_ref argv, std::error_code& ec) noexcept; -AW_IO_EXP int kill(process_handle pid, int signal, std::error_code& ec) noexcept; +AW_IO_EXP process_handle spawn(aw::array_view argv, std::error_code& ec) noexcept; -inline process_handle spawn(const char* path, aw::array_ref argv) +inline process_handle spawn(const char* path, aw::array_view argv) { std::error_code ec; return spawn(path, argv, ec); } -inline process_handle spawn(aw::array_ref argv) +inline process_handle spawn(aw::array_view argv) { std::error_code ec; return spawn(argv, ec); } -AW_IO_EXP process_handle spawn(std::string path, aw::array_ref argv); +AW_IO_EXP process_handle spawn(std::string path, aw::array_ref argv, std::error_code& ec); +AW_IO_EXP process_handle spawn(std::string path, aw::array_ref argv) +{ + std::error_code ec; + return spawn(path, argv, ec); +} + + +AW_IO_EXP wait_status wait(process_handle pid, std::error_code& ec) noexcept; +inline wait_status wait(process_handle pid) +{ + std::error_code ec; + return wait(pid, ec); +} +AW_IO_EXP int kill(process_handle pid, int signal, std::error_code& ec) noexcept; inline int kill(process_handle pid, int signal) { std::error_code ec; return kill(pid, signal, ec); } + + +inline wait_status run(std::string path, aw::array_ref argv, std::error_code& ec) +{ + auto handle = spawn(path, argv, ec); + if (handle == invalid_process_handle) + return wait_status::failed; + + return wait(handle, ec); +} + +inline wait_status run(std::string path, aw::array_ref argv) +{ + std::error_code ec; + return run(path, argv, ec); +} + +inline std::string executable_name(std::string path) +{ + return path; +} } // namespace aw::io::posix #endif // aw_io_posix_process_h diff --git a/io/include/aw/io/process.h b/io/include/aw/io/process.h index 1de3674d..3eefc63a 100644 --- a/io/include/aw/io/process.h +++ b/io/include/aw/io/process.h @@ -24,13 +24,16 @@ using posix::process_handle; using posix::invalid_process_handle; using posix::spawn; using posix::kill; +using posix::wait; +using posix::run; +using posix::executable_name; #elif (AW_PLATFORM == AW_PLATFORM_WIN32) using win32::invalid_process_handle; using win32::process_handle; using win32::spawn; -using win32::run; using win32::kill; using win32::wait; +using win32::run; using win32::executable_name; #endif } // namespace aw::platform diff --git a/io/include/aw/io/win32/process.h b/io/include/aw/io/win32/process.h index c4ee050b..2300befc 100644 --- a/io/include/aw/io/win32/process.h +++ b/io/include/aw/io/win32/process.h @@ -76,7 +76,7 @@ inline wait_status run( if (handle == invalid_process_handle) return wait_status::failed; - return wait(handle, ec); + return wait(handle, ec, timeout); } inline wait_status run(std::string path, aw::array_view argv, timeout_spec_ms timeout = {}) diff --git a/io/posix/process.c++ b/io/posix/process.c++ index 916c3059..dacf900f 100644 --- a/io/posix/process.c++ +++ b/io/posix/process.c++ @@ -1,17 +1,8 @@ -/* - * Copyright (C) 2016-2018 hedede - * - * License LGPLv3 or later: - * GNU Lesser GPL version 3 - * This is free software: you are free to change and redistribute it. - * There is NO WARRANTY, to the extent permitted by law. - */ -#include +#include "aw/io/posix/process.h" #include #include -#include #include #include @@ -26,15 +17,18 @@ extern char** environ; #endif -namespace aw::platform::posix { +namespace aw::io::posix { AW_IO_EXP -process_handle spawn(const char* path, aw::array_ref argv, std::error_code& ec) noexcept +process_handle spawn(const char* path, aw::array_view argv, std::error_code& ec) noexcept { /*! enforce `nullptr` at the end of `argv` */ assert( argv.empty() || argv.back() == nullptr ); pid_t pid; - int rc = posix_spawn(&pid, path, nullptr, nullptr, argv.data(), environ); + int rc = posix_spawnp(&pid, path, nullptr, nullptr, argv.data(), environ); + if (rc == 2) + rc = posix_spawn(&pid, path, nullptr, nullptr, argv.data(), environ); + if (rc == 0) return process_handle( pid ); @@ -43,15 +37,14 @@ process_handle spawn(const char* path, aw::array_ref argv, std::error_cod } AW_IO_EXP -process_handle spawn(aw::array_ref argv, std::error_code& ec) noexcept +process_handle spawn(aw::array_view argv, std::error_code& ec) noexcept { return spawn( argv[0], argv, ec ); } AW_IO_EXP -process_handle spawn(std::string path, aw::array_ref argv) +process_handle spawn(std::string path, aw::array_ref argv, std::error_code& ec) { - std::error_code ec; std::vector args; args.push_back(path.data()); for (std::string& arg : argv) @@ -75,4 +68,15 @@ int kill(process_handle pid, int signal, std::error_code& ec) noexcept ec.assign( errno, std::generic_category() ); return ret; } + +AW_IO_EXP wait_status wait(process_handle pid, std::error_code& ec) noexcept +{ + int status = 0; + pid_t ret = waitpid( pid_t(pid), &status, 0); + if (ret < 0) { + ec.assign( errno, std::generic_category() ); + return wait_status::failed; + } + return wait_status::finished; +} } // namespace aw::platform::posix diff --git a/io/tests/process.c++ b/io/tests/process.c++ index be64f014..62799d84 100644 --- a/io/tests/process.c++ +++ b/io/tests/process.c++ @@ -19,7 +19,8 @@ Test(process_basic_test) { auto path = io::executable_name("dump_args"s); - auto result = io::run(path, { "a", "b", "c" }); + std::vector in_args = { "a", "b", "c" }; + auto result = io::run(path, in_args); TestAssert(result == io::wait_status::finished);