
Question:
For a c++ program I'm working on, I have to call an external application to do some operations. I can't modify the application. This operations may take too much time so I have to add a timeout. I tried using system() and boost threads
int main()
{
[...]
boost::thread t(function1);
t.timed_join(boost::posix_time::seconds(10));
[...]
return 0;
}
void function1()
{
system("external application");
}
but when I return to the main 10 seconds later, the external application is still running in background. Using exec() instead of system() nothing works because I "lose" the main. What can I do? I'm on Linux.
Answer1:Use <a href="http://man7.org/linux/man-pages/man2/fork.2.html" rel="nofollow">fork(2)</a>, <a href="http://man7.org/linux/man-pages/man2/execve.2.html" rel="nofollow">execve(2)</a>, <a href="http://man7.org/linux/man-pages/man2/waitpid.2.html" rel="nofollow">waitpid(2)</a> instead of system
(which internally uses these syscalls). Read <a href="http://advancedlinuxprogramming.com" rel="nofollow">Advanced Linux Programming</a> which explains the <em>tricky</em> details.
You could want to use <a href="http://man7.org/linux/man-pages/man2/setrlimit.2.html" rel="nofollow">setrlimit(2)</a> in the child. Or in the parent <a href="http://man7.org/linux/man-pages/man2/kill.2.html" rel="nofollow">kill(2)</a> the child (first with SIGTERM
, then with SIGKILL
) on timeout.
You may want the child to make its own process group using <a href="http://man7.org/linux/man-pages/man2/setpgid.2.html" rel="nofollow">setpgid(2)</a> or setpgrp
, then kill the entire process group with <a href="http://man7.org/linux/man-pages/man2/killpg.2.html" rel="nofollow">killpg(2)</a>. This would kill both the child and any command it has started (unless these create there own process groups themselves).
You could handle the SIGCHLD
signal (see <a href="http://man7.org/linux/man-pages/man7/signal.7.html" rel="nofollow">signal(7)</a>) using <a href="http://man7.org/linux/man-pages/man2/sigaction.2.html" rel="nofollow">sigaction(2)</a>. SIGCHLD
would notably be sent when the child process terminates.
If you want to use <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html" rel="nofollow">exec
</a> you first have to <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html" rel="nofollow">fork
</a> a new process with does the actual exec
. Then after the timeout you can simply <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html" rel="nofollow">kill
</a> the child process. (And for the last you might want to read about <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html" rel="nofollow">signals</a>.)