2
0
mirror of https://github.com/boostorg/process.git synced 2026-01-20 16:52:14 +00:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Klemens Morgenstern
89c5b589c3 Fixed __FreeBSD__ code. 2022-09-14 15:37:56 +08:00
Klemens Morgenstern
4183c66490 Removed android check. 2022-09-14 15:18:34 +08:00
Klemens Morgenstern
9cdc1be868 Ported enum_pids from xproc
Credit to Samuel Venable, @time-killer-games.
2022-09-14 15:15:49 +08:00
Klemens Morgenstern
b9cb5dc0ee Added suspend & resume functions.
Credit to Samuel Venable, @time-killer-games
2022-09-14 12:39:11 +08:00
11 changed files with 448 additions and 0 deletions

View File

@@ -12,6 +12,16 @@
#include <windows.h>
#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API)
extern "C"
{
LONG WINAPI NtResumeProcess(HANDLE ProcessHandle);
LONG WINAPI NtSuspendProcess(HANDLE ProcessHandle);
}
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace detail
@@ -113,6 +123,33 @@ void check_running_(HANDLE handle, error_code & ec, DWORD & exit_status)
ec = detail::get_last_error();
}
#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API)
void suspend_(HANDLE handle, error_code & ec)
{
auto nt_err = NtSuspendProcess(handle);
if (nt_err > 0xC0000000)
ec = detail::get_last_error();
}
void resume_(HANDLE handle, error_code & ec)
{
auto nt_err = NtResumeProcess(handle);
if (nt_err > 0xC0000000)
ec = detail::get_last_error();
}
#else
void suspend_(HANDLE, error_code & ec)
{
ec.assign(ERROR_CALL_NOT_IMPLEMENTED, system_category());
}
void resume_(HANDLE handle, error_code & ec)
{
ec.assign(ERROR_CALL_NOT_IMPLEMENTED, system_category());
}
#endif
#if !defined(BOOST_PROCESS_V2_HEADER_ONLY)
template struct basic_process_handle_win<>;

View File

@@ -182,7 +182,42 @@ struct basic_process_handle_fd
if (ec)
detail::throw_error(ec, "request_exit");
}
void suspend()
{
if (pid_ <= 0)
return ;
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "suspend");
}
void suspend(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGCONT) == -1)
ec = get_last_error();
}
void resume()
{
if (pid_ <= 0)
return ;
error_code ec;
resume(ec);
if (ec)
detail::throw_error(ec, "resume");
}
void resume(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGTERM) == -1)
ec = get_last_error();
}
void terminate(native_exit_code_type &exit_status, error_code &ec)
{
if (pid_ <= 0)

View File

@@ -211,6 +211,42 @@ struct basic_process_handle_fd_or_signal
if (ec)
detail::throw_error(ec, "request_exit");
}
void suspend()
{
if (pid_ <= 0)
return ;
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "suspend");
}
void suspend(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGCONT) == -1)
ec = get_last_error();
}
void resume()
{
if (pid_ <= 0)
return ;
error_code ec;
resume(ec);
if (ec)
detail::throw_error(ec, "resume");
}
void resume(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGTERM) == -1)
ec = get_last_error();
}
void terminate(native_exit_code_type &exit_status, error_code &ec)
{

View File

@@ -180,6 +180,50 @@ struct basic_process_handle_signal
detail::throw_error(ec, "request_exit");
}
void interrupt(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGTERM) == -1)
ec = get_last_error();
}
void suspend()
{
if (pid_ <= 0)
return ;
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "suspend");
}
void suspend(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGCONT) == -1)
ec = get_last_error();
}
void resume()
{
if (pid_ <= 0)
return ;
error_code ec;
resume(ec);
if (ec)
detail::throw_error(ec, "resume");
}
void resume(error_code &ec)
{
if (pid_ <= 0)
return ;
if (::kill(pid_, SIGTERM) == -1)
ec = get_last_error();
}
void terminate(native_exit_code_type &exit_status, error_code &ec)
{
if (pid_ <= 0)

View File

@@ -32,6 +32,8 @@ BOOST_PROCESS_V2_DECL void terminate_if_running_(void * handle);
BOOST_PROCESS_V2_DECL bool check_handle_(void* handle, error_code & ec);
BOOST_PROCESS_V2_DECL bool check_pid_(pid_type pid_, error_code & ec);
BOOST_PROCESS_V2_DECL void interrupt_(pid_type pid_, error_code & ec);
BOOST_PROCESS_V2_DECL void suspend_(void * handle, error_code & ec);
BOOST_PROCESS_V2_DECL void resume_(void * handle, error_code & ec);
BOOST_PROCESS_V2_DECL void terminate_(void * handle, error_code & ec, native_exit_code_type & exit_code);
BOOST_PROCESS_V2_DECL void request_exit_(pid_type pid_, error_code & ec);
BOOST_PROCESS_V2_DECL void check_running_(void* handle, error_code & ec, native_exit_code_type & exit_status);
@@ -176,6 +178,32 @@ struct basic_process_handle_win
detail::throw_error(ec, "request_exit");
}
void suspend(error_code &ec)
{
detail::suspend_(handle_.native_handle(), ec);
}
void suspend()
{
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "suspend");
}
void resume(error_code &ec)
{
detail::resume_(handle_.native_handle(), ec);
}
void resume()
{
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "resume");
}
void terminate(native_exit_code_type &exit_status, error_code &ec)
{
if (!detail::check_handle_(handle_.native_handle(), ec))

View File

@@ -6,12 +6,21 @@
#define BOOST_PROCESS_V2_IMPL_PID_IPP
#include <boost/process/v2/detail/config.hpp>
#include <boost/process/v2/detail/last_error.hpp>
#include <boost/process/v2/detail/throw_error.hpp>
#include <boost/process/v2/pid.hpp>
#if defined(BOOST_PROCESS_V2_WINDOWS)
#include <windows.h>
#include <tlhelp32.h>
#else
#include <unistd.h>
#if (defined(__APPLE__) && defined(__MACH__))
#include <sys/proc_info.h>
#include <libproc.h>
#endif
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
@@ -22,6 +31,220 @@ pid_type current_pid() {return ::GetCurrentProcessId();}
pid_type current_pid() {return ::getpid();}
#endif
#if defined(BOOST_PROCESS_V2_WINDOWS)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (!hp)
{
ec = detail::get_last_error();
return vec;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hp, &pe)) {
do {
vec.push_back(pe.th32ProcessID);
} while (Process32Next(hp, &pe));
}
CloseHandle(hp);
return vec;
}
#elif (defined(__APPLE__) && defined(__MACH__))
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
vec.resize(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0));
if (proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec))
{
ec = detail::get_last_error();
return {};
}
auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;});
vec.erase(itr, vec.end());
return vec;
}
#elif defined(__linux__)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
DIR *proc = opendir("/proc");
if (proc == nullptr)
{
ec = detail::get_last_error();
return vec;
}
struct dirent *ent = nullptr;
while ((ent = readdir(proc) != nullptr))
{
if (!isdigit(*ent->d_name))
continue;
vec.push_back(atoi(ent->d_name));
}
closedir(proc);
return vec;
}
#elif defined(__FreeBSD__)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
int cntp = 0;
kinfo_proc *proc_info = kinfo_getallproc(&cntp);
if (proc_info)
{
for (int i = 0; i < cntp; i++)
vec.push_back(proc_info[i].ki_pid);
free(proc_info);
}
else
ec = detail::get_last_error();
return vec;
}
#elif defined(__DragonFly__)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
int cntp = 0;
kinfo_proc *proc_info = nullptr;
const char *nlistf, *memf;
nlistf = memf = "/dev/null";
kd = kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr);
if (!kd)
{
ec = detail::get_last_error();
return vec;
}
if ((proc_info = kvm_getprocs(kd, KERN_PROC_ALL, 0, &cntp)))
{
vec.reserve(cntp);
for (int i = 0; i < cntp; i++)
if (proc_info[i].kp_pid >= 0)
vec.push_back(proc_info[i].kp_pid);
}
else
ec = detail::get_last_error();
kvm_close(kd);
return vec;
}
#elif defined(__NetBSD__)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
int cntp = 0;
kinfo_proc2 *proc_info = nullptr;
kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr);
if (!kd)
{
ec = detail::get_last_error();
return vec;
}
if ((proc_info = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
{
vec.reserve(cntp);
for (int i = cntp - 1; i >= 0; i--) {
vec.push_back(proc_info[i].p_pid);
}
}
else
ec = detail::get_last_error();
kvm_close(kd);
return vec;
}
#elif defined(__OpenBSD__)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
int cntp = 0;
kinfo_proc *proc_info = nullptr;
kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr);
if (!kd)
{
ec = detail::get_last_error();
return vec;
}
if ((proc_info = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
{
vec.reserve(cntp);
for (int i = 0; i < cntp; i++) {
if (proc_info[i].kp_pid >= 0) {
vec.push_back(proc_info[i].kp_pid);
}
}
}
else
ec = detail::get_last_error();
kvm_close(kd);
return vec;
}
#elif defined(__sun)
std::vector<pid_type> all_pids(error_code & ec)
{
std::vector<pid_type> vec;
struct pid cur_pid;
proc *proc_info = nullptr;
kd = kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr);
if (!kd)
{
ec = detail::get_last_error();
return vec;
}
while ((proc_info = kvm_nextproc(kd)))
{
if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1) {
vec.insert(vec.begin(), cur_pid.pid_id);
}
else
{
ec = detail::get_last_error();
break;
}
}
kvm_close(kd);
return vec;
}
#else
#error "Platform not supported"
#endif defined(BOOST_PROCESS_V2_WINDOWS)
std::vector<pid_type> all_pids()
{
error_code ec;
auto res = all_pids(ec);
if (ec)
detail::throw_error(ec, "all_pids");
return res;
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif //BOOST_PROCESS_V2_IMPL_PID_IPP

View File

@@ -6,6 +6,7 @@
#define BOOST_PROCESS_V2_PID_HPP
#include <boost/process/v2/detail/config.hpp>
#include <boost/process/v2/detail/throw_error.hpp>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
@@ -31,6 +32,12 @@ typedef int pid_type;
/// Get the process id of the current process.
BOOST_PROCESS_V2_DECL pid_type current_pid();
/// List all available pids.
BOOST_PROCESS_V2_DECL std::vector<pid_type> all_pids(error_code & ec);
/// List all available pids.
BOOST_PROCESS_V2_DECL std::vector<pid_type> all_pids();
BOOST_PROCESS_V2_END_NAMESPACE
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)

View File

@@ -214,6 +214,37 @@ struct basic_process
process_handle_.request_exit(ec);
}
/// Send the process a signal requesting it to stop. This may rely on undocmented functions.
void suspend(error_code &ec)
{
process_handle_.suspend(ec);
}
/// Send the process a signal requesting it to stop. This may rely on undocmented functions.
void suspend()
{
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "suspend");
}
/// Send the process a signal requesting it to resume. This may rely on undocmented functions.
void resume(error_code &ec)
{
process_handle_.resume(ec);
}
/// Send the process a signal requesting it to resume. This may rely on undocmented functions.
void resume()
{
error_code ec;
suspend(ec);
if (ec)
detail::throw_error(ec, "resume");
}
/// Throwing @overload void terminate(native_exit_code_type &exit_code, error_code & ec)
void terminate()
{

View File

@@ -46,6 +46,7 @@ lib test_impl : test_impl.cpp filesystem :
<link>static
<target-os>windows:<source>shell32
<target-os>windows:<source>user32
<target-os>windows:<source>Ntdll
;
test-suite standalone :

View File

@@ -12,4 +12,8 @@ BOOST_AUTO_TEST_CASE(test_pid)
{
namespace bp2 = boost::process::v2;
BOOST_CHECK_NE(bp2::current_pid(), static_cast<bp2::pid_type>(0));
auto all = bp2::all_pids();
auto itr = std::find(all.begin(), all.end(), bp2::current_pid());
BOOST_CHECK(itr != all.end());
}

View File

@@ -149,6 +149,8 @@ BOOST_AUTO_TEST_CASE(terminate)
BOOST_CHECK_MESSAGE(!sh.empty(), sh);
bpv::process proc(ctx, sh, {});
proc.suspend();
proc.resume();
proc.terminate();
proc.wait();
}