process-cpp

process-cpp is a simple and straightforward wrapper around process creation and control targeted towards linux. It helps both with handling child processes and with interacting with the current process. Some of its features include:

- Thread-safe get/set/unset operation on the current process's environment.
- Throwing and non-throwing overloads of functions when system calls are involved.
- Seamless redirection of input, output and error streams of child processes.
- Type-safe interaction with the virtual proc filesystem, both for reading & writing.

The library's main purpose is to assist in testing and when a software component needs to carry out process creation/control tasks, e.g., a graphical shell. To this end, the library is extensively tested and tries to ensure fail-safe operation as much as possible.

# A simple echo

// Fork and run a simple echo:
posix::ChildProcess child = posix::fork(
[]()
{
std::string line;
while(true)
{
std::cin >> line;
std::cout << line << std::endl;
}
return EXIT_FAILURE;
},
posix::StandardStreamFlags()
.set(posix::StandardStream::stdin)
.set(posix::StandardStream::stdout));
// Check that the resulting process has a valid pid.
EXPECT_TRUE(child.pid() > 0);
// Check on echo functionality.
const std::string echo_value{"42"};
child.cin() << echo_value << std::endl;
std::string line; child.cout() >> line;
EXPECT_EQ(echo_value, line);
// Stop the process and synchronize with the process changing state.
EXPECT_NO_THROW(child.send_signal(posix::Signal::sig_stop));
auto result = child.wait_for(posix::wait::Flag::untraced);
EXPECT_EQ(posix::wait::Result::Status::stopped,
result.status);
EXPECT_EQ(posix::Signal::sig_stop,
result.detail.if_stopped.signal);
// Kill the stopped process and synchronize to its state change.
EXPECT_NO_THROW(child.send_signal(posix::Signal::sig_kill));
result = child.wait_for(posix::wait::Flag::untraced);
EXPECT_EQ(posix::wait::Result::Status::signaled,
result.status);
EXPECT_EQ(posix::Signal::sig_kill,
result.detail.if_signaled.signal);

# Adjusting OOM Score Values

// Setup the manipulator with a well-known value.
posix::linux::proc::process::OomScoreAdj oom_score_adj
{
posix::linux::proc::process::OomScoreAdj::max_value()
};
// Apply the manipulator to the current process
EXPECT_NO_THROW(posix::this_process::instance() << oom_score_adj);
// Read back the manipulators value for the current process
EXPECT_NO_THROW(posix::this_process::instance() >> oom_score_adj);
// And check that applying the manipulator was successful.
EXPECT_EQ(posix::linux::proc::process::OomScoreAdj::max_value(),
oom_score_adj.value);
// Instantiate the observer...
posix::linux::proc::process::OomScore oom_score;
// ... and fill in its value for the current process.
EXPECT_NO_THROW(posix::this_process::instance() >> oom_score);
// Check that applying the manipulator before results in adjustments to the
// OOM score.
EXPECT_TRUE(is_approximately_equal(oom_score.value, posix::linux::proc::process::OomScoreAdj::max_value()));
core::posix::this_process::instance
CORE_POSIX_DLL_PUBLIC Process instance() noexcept(true)
Returns a Process instance corresponding to this process.
Definition: this_process.cpp:150
core::posix::fork
CORE_POSIX_DLL_PUBLIC ChildProcess fork(const std::function< posix::exit::Status()> &main, const StandardStream &flags)
fork forks a new process and executes the provided main function in the newly forked process.
Definition: fork.cpp:57
core::posix::this_process::cin
CORE_POSIX_DLL_PUBLIC std::istream & cin() noexcept(true)
Access this process's stdin.
Definition: this_process.cpp:161
core::posix::this_process::cout
CORE_POSIX_DLL_PUBLIC std::ostream & cout() noexcept(true)
Access this process's stdout.
Definition: this_process.cpp:166
core::posix::ChildProcess::cin
std::ostream & cin()
Access this process's stdin.
Definition: child_process.cpp:387