tags:

views:

195

answers:

6

In Linux I would like to run a program but only for a limited time, like 1 second. If the program exceeds this running time I would like to kill the process and show an error message.

+1  A: 

you could launch it in a shell script using &

your_program &
pid=$!
sleep 1
if [ `pgrep $pid` ]
  then
    kill $pid
    echo "killed $pid because it took too long."
fi

hope you get the idea, I'm not sure this is correct my shell skills need some refresh :)

f4
A: 

If you have the sources, you can fork() early in main() and then have the parent process measure the time and possibly kill the child process. Just use standard system calls fork(), waitpid(), kill(), ... maybe some standard Unix signal handling. Not too complicated but takes some effort.

You can also script something on the shell although I doubt it will be as accurate with respect to the time of 1 second.

If you just want to measure the time, type time <cmd ...> on the shell.

This was the way i thought of doing it in the first time. But I need the program to work without access to the source files. Thanks for the answer
Overdeath
+7  A: 

Maybe CPU time limit (ulimit -t/setrlimit(RLIMIT_CPU)) will help?

wRAR
+1 for a very cool approach! :)
roe
How could i check if the program exceeded the running time?
Overdeath
@Overdeath: You'd probably have to make your own program `fork`, `setrlimit` and `waitpid`, and then check if it got killed by a SIGXCPU. You could also check the return value of your program, bash usually sets `$?` to something high when it's killed by a signal. Don't know if it possible to determine whether it's SIGXCPU though.
roe
@Overdeath It will be killed by SIGXCPU if it exceeds the softlimit; if it ignores that and hits the hardlimit, it will be killed by SIGKILL. In shell, $? will be 128+signal if the process was killed by a signal; in C, check `WIFSIGNALED(status)` and `WTERMSIG(status)`, if `status` was returned by `wait*`.
ephemient
+16  A: 

A simple bash-script should be able to do that for you

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

That ought to do it.

$! expands to the last backgrounded process (through the use of &), and kill returns false if it didn't kill any process, so the echo is only executed if it actually killed something.

2>/dev/null redirects kill's stderr, otherwise it would print something telling you it was unable to kill the process.

You might want to add a -KILL or whichever signal you want to use to get rid of your process too.

EDIT
As ephemient pointed out, there's a race here if your program finishes and the some other process snatches the pid, it'll get killed instead. To reduce the probability of it happening, you could react to the SIGCHLD and not try to kill it if that happens. There's still chance to kill the wrong process, but it's very remote.

trapped=""
trap 'trapped=yes' SIGCHLD
./myProgram &
sleep 1
[ -z "$trapped" ] && kill $! 2>/dev/null && echo '...'
roe
This worked.. thanks
Overdeath
ephemient
@ephemient: yeah, I considered that too. won't eliminate the race completely, but it'll certainly shrink the window.
roe
I actually don't think there's a window in the new procedure, because the PID can only be reused after the original process has been reaped, which (if we haven't trapped) hasn't happened yet.
ephemient
@ephemient: I'm not sure exactly how bash handles it, you might be right. Question is if it could execute the trap after spawning the kill process, but before that process got to the killing...
roe
ephemient
A: 

Ok, so just write a short C program that forks, calls execlp or something similar in the child, measures the time in the parent and kills the child. Should be easy ...

A: 

Ah well. timeout(1).

DESCRIPTION
Start COMMAND, and kill it if still running after DURATION.

wRAR
Please comment on downvoting.
wRAR