From C , I wish to submit a process, pause, resume it and stop it. For this, I am first using the following function to run a shell process in the background and save the associate PID. I found the function at this post (and only removed the standard input and output).
int system2(const char * command)
{
int p_stdin[2];
int p_stdout[2];
int pid;
if (pipe(p_stdin) == -1)
return -1;
if (pipe(p_stdout) == -1) {
close(p_stdin[0]);
close(p_stdin[1]);
return -1;
}
pid = fork();
if (pid < 0) {
close(p_stdin[0]);
close(p_stdin[1]);
close(p_stdout[0]);
close(p_stdout[1]);
return pid;
} else if (pid == 0) {
close(p_stdin[1]);
dup2(p_stdin[0], 0);
close(p_stdout[0]);
dup2(p_stdout[1], 1);
dup2(::open("/dev/null", O_RDONLY), 2);
/// Close all other descriptors for the safety sake.
for (int i = 3; i < 4096; i)
::close(i);
setsid();
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(1);
}
close(p_stdin[0]);
close(p_stdout[1]);
return pid;
}
Then, I am using the kill
function, to pause, resume and stop the process but it does not work as I expected. Here is an example:
int main()
{
// The process prints on file allowing me to figure out whether the process is paused / stopped, or is running
const char * command = "for i in {1..1000}; do echo $i >> /Users/remi/test/data.txt; sleep 1s;done";
// Run the command and record pid
auto pid = system2(command);
std::cout << "pid = " << pid << "\n";
// with this pid, I could ensure that `ps -p <pid>` returns the correct command
std::cout << "process should be running!\n"; // It is!
// wait
std::this_thread::sleep_for(std::chrono::seconds(10));
// pause
kill(pid, SIGTSTP);
std::cout << "process should be paused!\n"; // But it is not!
// wait
std::this_thread::sleep_for(std::chrono::seconds(10));
// resume process
kill(pid, SIGCONT);
std::cout << "process should be running!\n"; // Sure, it is as it has never been stopped
// wait
std::this_thread::sleep_for(std::chrono::seconds(10));
// Kill process
kill(pid, SIGSTOP);
std::cout << "process should be stopped!\n"; // That worked!
// wait
std::this_thread::sleep_for(std::chrono::seconds(10));
}
Can you please help me figure out how to fix this code to ensure the process stops and resume as I was expected.
FYI, I am on a macOS and wish the solution work on any POSIX system.
CodePudding user response:
Note that both SIGTSTP
and SIGSTOP
signals are actually pausing the process. The first can be ignored by the process but the latter can’t be. If you wish to pause the process no matter what use SIGSTOP
.
To kill the process, use SIGTERM
or SIGKILL
.