Killing a child process if it takes too much time - c++

When using the fork system call in C++, what is the easiest way to kill a child process if it takes too much time to execute what it is supposed to execute?
Like if somehow it gets into an infinite loop.. What should the parent process do to set the timeout for the child process?

Use WNOHANG with waitpid and sleep in between. Something like this should do it:
while (times < max_times) {
sleep(5); /* sleep 5 seconds */
rc = waitpid(-1, &status, WNOHANG);
if (rc < 0) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status) || WIFSIGNALED(status)) {
/* it's done */
break;
}
times++;
}
if (times == max_times) {
/* ... */
}

I think you need waitpid with timeout and on timeout kill child process (assuming that child is hung). Check this page for ideas:
Waitpid equivalent with timeout?

Related

I want to restart my program after the few seconds what I set

In present, I try to make a watchdog for my project.
Also, I want to make a restart timer.
I mean if the few seconds pass, the program will start from first.
Surely, I can use while loop in main function. I don't want this.
I just want to make some class such as a timer or watchdog,
After the main function passes the time I set, I want to let my program start again.
Is there any good idea?
int main(void)
{
Timer timer(5) // setting my timer to 5 secs
//If time takes over the 5 secs in this loop,
//I want to restart the main loop.
while(1)
{
//Do Something...
}
return 0;
}
If you can get your code to keep an eye on the clock and voluntarily return after so-many-seconds have elapsed, that's usually the best way; however, since you mentioned a watchdog, it sounds like you don't want to trust your code to do that, so (assuming you have an OS that supports fork()) you can spawn a child process to run the code, and then the parent process can unilaterally kill() the child process after 5 seconds and then launch a new one. Here's an example, with a child process counting a random number of potatoes, one per second; if it tries to count more than 5 of them, it will be killed by the parent process.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
// The code you want to be able to abort and restart would go in here
static void FunctionThatMightTakeALongTime()
{
srand(time(NULL)); // just so we get different random values each time
const int countTo = (rand()%12)+1;
for (int i=0; i<countTo; i++)
{
printf("%i potato... (out of %i)\n", i+1, countTo);
sleep(1);
}
}
int main(int argc, char ** argv)
{
while(1)
{
pid_t pid = fork();
if (pid == -1)
{
perror("fork"); // fork() failed!?
return 10;
}
else if (pid == 0)
{
// We're in the child process -- do the thing
printf("Starting child process...\n");
FunctionThatMightTakeALongTime();
printf("Child process completed!\n");
return 0;
}
else
{
// We're in the parent/watchdog process -- wait
// 5 seconds, and then if the child process is
// still running, send it a SIGKILL signal to kill it.
// (if OTOH it has already exited, the SIGKILL isn't
// required but it won't do any harm either)
sleep(5);
printf("Watchdog: killing child process now\n");
if (kill(pid, SIGKILL) != 0) perror("kill");
// Now call waitpid() to pick up the child process's
// return code (otherwise he'll stick around as a zombie process)
if (waitpid(pid, NULL, 0) == -1) perror("waitpid");
}
}
}
Note: If your OS doesn't support fork() (i.e. your OS is Windows), this technique is still possible, but it requires the use of Windows-specific APIs and is significantly more work to implement.

child process hanging while reading from stdin (fork/dup2 race condition)?

I have a process that forks in order to execute a subprocess, which receive an entry from stdin and writes to stdout.
My code in short is as follows:
int fd[2];
int fd2[2];
if (pipe(fd) < 0 || pipe(fd2) < 0)
throws exception;
pid_t p = fork();
if (p == 0) // child
{
close(fd[0]); //not needed
dup2( fd[1],STDOUT_FILENO);
dup2( fd[1],STDERR_FILENO);
close(fd2[1]); //not needed
//what if write calls on parent process execute first?
//how to handle that situation
dup2( fd2[0],STDIN_FILENO);
string cmd="./childbin";
if (execl(cmd.c_str(),(char *) NULL) == -1)
{
exit (-1);
}
exit(-1);
}
else if (p > 0) // parent
{
close(fd[1]); //not needed
close(fd2[0]);
if (write(fd2[1],command.c_str(),command.size())<0)
{
throw exception;
}
close(fd2[1]);
//waits for child to finish.
//child process actually hangs on reading for ever from stdin.
pidret=waitpid(p,&status,WNOHANG))==0)
.......
}
The child process remains waiting forever for data in STDIN. Is there maybe a race condition between the child and parent process? I think that could be the problem but not quite sure and also not sure how to fix it.
Thanks in advance.
Update:
Some useful information.
The parent process is a daemon and this code runs several times per second. It works 97% of the times (~3% of the cases, the child process remains in the state described before).
UPDATE 2
After added validation in dup2 call, there is no error there, next condition is never raised.
if(dup2(...) == -1) {
syslog(...)
}
Your missing a wait that is why you in 3% of the cases run the parent before the child. See the example at the bottom.
Also you should call close on the fd's you don't use before doing anything else.

Input command with system() and sleep()

Is there a way to use system() and ask for the code to wait a few seconds?
I have been trying something like:
system("MyCmd");
sleep(8000);
However, sleep() terminates "MyCmd" execution.
Any thoughts?
However, sleep() terminates "MyCmd" execution.
No. The sleep() expression doesn't terminate the child process created with the system() call, the expressions
system("MyCmd");
sleep(8000);
will just be executed sequentially.
What you can do is to call fork() to create a child process, call sleep() in the parent process, and kill() the child process, if it's still running after the parent process awakes:
pid_t pid = fork();
if (pid == 0) {
// child process
execl ("/bin/MyCmd", "MyCmd", (char *)0);
}
else if (pid > 0) {
// parent process
sleep(8000);
kill(pid,SIGKILL);
}
else {
// fork failed
printf("fork() failed!\n");
return 1;
}

Child process is blocked by full pipe, cannot read in parent process

I have roughly created the following code to call a child process:
// pipe meanings
const int READ = 0;
const int WRITE = 1;
int fd[2];
// Create pipes
if (pipe(fd))
{
throw ...
}
p_pid = fork();
if (p_pid == 0) // in the child
{
close(fd[READ]);
if (dup2(fd[WRITE], fileno(stdout)) == -1)
{
throw ...
}
close(fd[WRITE]);
// Call exec
execv(argv[0], const_cast<char*const*>(&argv[0]));
_exit(-1);
}
else if (p_pid < 0) // fork has failed
{
throw
}
else // in th parent
{
close(fd[WRITE]);
p_stdout = new std::ifstream(fd[READ]));
}
Now, if the subprocess does not write too much to stdout, I can wait for it to finish and then read the stdout from p_stdout. If it writes too much, the write blocks and the parent waits for it forever.
To fix this, I tried to wait with WNOHANG in the parent, if it is not finished, read all available output from p_stdout using readsome, sleep a bit and try again. Unfortunately, readsome never reads anything:
while (true)
{
if (waitid(P_PID, p_pid, &info, WEXITED | WNOHANG) != 0)
throw ...;
else if (info.si_pid != 0) // waiting has succeeded
break;
char tmp[1024];
size_t sizeRead;
sizeRead = p_stdout->readsome(tmp, 1024);
if (sizeRead > 0)
s_stdout.write(tmp, sizeRead);
sleep(1);
}
The question is: Why does this not work and how can I fix it?
edit: If there is only child, simply using read instead of readsome would probably work, but the process has multiple children and needs to react as soon as one of them terminates.
As sarnold suggested, you need to change the order of your calls. Read first, wait last. Even if your method worked, you might miss the last read. i.e. you exit the loop before you read the last set of bytes that was written.
The problem might be is that ifstream is non-blocking. I've never liked iostreams, even in my C++ projects, I always liked the simplicity of C's stdio functions (i.e. FILE*, fprintf, etc). One way to get around this is to read if the descriptor is readable. You can use select to determine if there is data waiting on that pipe. You're going to need select if you are going to read from multiple children anyway, so might as well learn it now.
As for a quick isreadable function, try something like this (please note I haven't tried compiling this):
bool isreadable(int fd, int timeoutSecs)
{
struct timeval tv = { timeoutSecs, 0 };
fd_set readSet;
FD_ZERO(&readSet);
return select(fds, &readSet, NULL, NULL, &tv) == 1;
}
Then in your parent code, do something like:
while (true) {
if (isreadable(fd[READ], 1)) {
// read fd[READ];
if (bytes <= 0)
break;
}
}
wait(pid);
I'd suggest re-writing the code so that it doesn't call waitpid(2) until after read(2) calls on the pipe return 0 to signify end-of-file. Once you get the end-of-file return from your read calls, you know the child is dead, and you can finally waitpid(2) for it.
Another option is to de-couple the reading from the reaping even further and perform the wait calls in a SIGCHLD signal handler asynchronously to the reading operations.

How can I run an external program without waiting for it to exit?

I'm trying to execute an external program from inside my Linux C++ program.
I'm calling the method system("gedit") to launch an instance of the Gedit editor. However my problem is while the Gedit window is open, my C++ program waits for it to exit.
How can I call an external program without waiting for it to exit?
You will need to use fork and exec
int fork_rv = fork();
if (fork_rv == 0)
{
// we're in the child
execl("/path/to/gedit", "gedit", 0);
// in case execl fails
_exit(1);
}
else if (fork_rv == -1)
{
// error could not fork
}
You will also need to reap your child so as not to leave a zombie process.
void reap_child(int sig)
{
int status;
waitpid(-1, &status, WNOHANG);
}
int main()
{
signal(SIGCHLD, reap_child);
...
}
In regards to zombie processes, you have a second option. It uses a bit more resources (this flavor forks twice), but the benefit is you can keep your wait closer to your fork which is nicer in terms of maintenance.
int fork_rv = fork();
if (fork_rv == 0)
{
fork_rv = fork();
if (fork_rv == 0)
{
// we're in the child
execl("/path/to/gedit", "gedit", 0);
// if execl fails
_exit(1);
}
else if (fork_rv == -1)
{
// fork fails
_exit(2);
}
_exit(0);
}
else if (fork_rv != -1)
{
// parent wait for the child (which will exit quickly)
int status;
waitpid(fork_rv, &status, 0);
}
else if (fork_rv == -1)
{
// error could not fork
}
What this last flavor does is create a child, which in turns creates a grandchild and the grandchild is what exec's your gedit program. The child itself exits and the parent process can reap it right away. So an extra fork but you keep all the code in one place.
Oh, let me say it!
http://en.wikipedia.org/wiki/Fork-exec
Fork! :)
First, did you try to launch in background with system("gedit&")?
If that does not work, try spawning a new thread and running gedit from there.
I presume that you are not concerned with the result of the edit, or the contents of the edited file?