2016-06-14 23:32:35 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
#include "common.hpp"
|
|
|
|
#include "utils/string.hpp"
|
|
|
|
|
|
|
|
LEMONBUDDY_NS
|
|
|
|
|
|
|
|
namespace process_util {
|
|
|
|
/**
|
|
|
|
* Check if currently in main process
|
|
|
|
*/
|
|
|
|
inline auto in_parent_process(pid_t pid) {
|
|
|
|
return pid != -1 && pid != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if currently in subprocess
|
|
|
|
*/
|
|
|
|
inline auto in_forked_process(pid_t pid) {
|
|
|
|
return pid == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace process with command
|
|
|
|
*/
|
|
|
|
inline auto exec(string cmd) {
|
|
|
|
vector<char*> c_args;
|
|
|
|
vector<string> args;
|
|
|
|
|
|
|
|
if (string_util::contains(cmd, "\n"))
|
|
|
|
string_util::split_into(cmd, '\n', args);
|
|
|
|
else
|
|
|
|
string_util::split_into(cmd, ' ', args);
|
|
|
|
|
|
|
|
for (auto&& argument : args) c_args.emplace_back(const_cast<char*>(argument.c_str()));
|
|
|
|
c_args.emplace_back(nullptr);
|
|
|
|
|
|
|
|
execvp(c_args[0], c_args.data());
|
|
|
|
|
|
|
|
throw system_error("Failed to execute command");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wait for child process
|
|
|
|
*/
|
|
|
|
inline auto wait_for_completion(pid_t process_id, int* status_addr, int waitflags = 0) {
|
|
|
|
int saved_errno = errno;
|
|
|
|
auto retval = waitpid(process_id, status_addr, waitflags);
|
|
|
|
errno = saved_errno;
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wait for child process
|
|
|
|
*/
|
|
|
|
inline auto wait_for_completion(int* status_addr, int waitflags = 0) {
|
|
|
|
return wait_for_completion(-1, status_addr, waitflags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wait for child process
|
|
|
|
*/
|
|
|
|
inline auto wait_for_completion(pid_t process_id) {
|
|
|
|
int status = 0;
|
|
|
|
return wait_for_completion(process_id, &status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Non-blocking wait
|
|
|
|
*
|
|
|
|
* @see wait_for_completion
|
|
|
|
*/
|
|
|
|
inline auto wait_for_completion_nohang(pid_t process_id, int* status) {
|
|
|
|
return wait_for_completion(process_id, status, WNOHANG);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Non-blocking wait
|
|
|
|
*
|
|
|
|
* @see wait_for_completion
|
|
|
|
*/
|
|
|
|
inline auto wait_for_completion_nohang(int* status) {
|
|
|
|
return wait_for_completion_nohang(-1, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Non-blocking wait
|
|
|
|
*
|
|
|
|
* @see wait_for_completion
|
|
|
|
*/
|
|
|
|
inline auto wait_for_completion_nohang() {
|
|
|
|
int status = 0;
|
|
|
|
return wait_for_completion_nohang(-1, &status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Non-blocking wait call which returns pid of any child process
|
|
|
|
*
|
|
|
|
* @see wait_for_completion
|
|
|
|
*/
|
|
|
|
inline auto notify_childprocess() {
|
|
|
|
return wait_for_completion_nohang() > 0;
|
|
|
|
}
|
2016-10-15 07:15:56 -04:00
|
|
|
|
|
|
|
inline auto unblock_signal(int sig) {
|
|
|
|
sigset_t sigmask;
|
|
|
|
sigemptyset(&sigmask);
|
|
|
|
sigaddset(&sigmask, sig);
|
|
|
|
if (pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr) == -1)
|
|
|
|
throw system_error("Failed to change pthread_sigmask");
|
|
|
|
}
|
2016-06-14 23:32:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
LEMONBUDDY_NS_END
|