Suppose I run a program that I suspect to contain an infinite loop, or some other code that might run for too long. I know that in Linux I can do:

timeout 1 ./program

to give the program a time-out of 1 second. But, if I understand correctly, this will only send a "SIGTERM" signal to the program - the program might ignore it. What is a safer way to ensure that the program stops after 1 second, no matter what?

One solution I thought of is to run the program in bash and timeout bash, like this:

timeout 1 bash -c './program'

Then, after 1 second, bash is terminated and so the program it runs is terminated too. Is this a good solution?

  • Your second example with bash -c still only sends a signal (like SIGTERM) to your program. It can still be ignored. – Philip Couling Mar 11 at 11:56
  • @PhilipCouling does bash ignore this signal? I expected bash to terminate when it gets SIGTERM. – Erel Segal-Halevi Mar 11 at 12:00
  • Bash scripts don't ignore them, but they do occasionally get stuck waiting for their child process to terminate after a SIGTERM is sent. – Philip Couling Mar 11 at 12:13

This really depends on what you mean by "safe". You have two options to kill a process:

  • Politely ask the process to terminate itself (eg with SIGTERM)
  • In-politely demand the kernel to forcibly kill it (Eg: kill -9)

In most cases the cleanest and "safest" way to terminate a process is to ask it politely with SIGTERM. That's because by default programs will propagate the SIGTERM to all of their children and thus clean up the whole process tree. It's also better because the terminating processes have time to close down what they were doing cleanly (flushing buffers etc).

Where you forcibly kill a process, this does not necessarily (or even by default) kill the child processes. It has a tendency to leave orphans. It also has a tendency to corrupt files and generally cause a bit of a mess. So cleaning up with a force kill (kill -9) should not be done automatically.

Bash scripts are particularly tricky to clean up. By default they will propagate the SIGTERM to their child processes and wait for their child processes to terminate. If for some reason you send SIGTERM to a bash script and it doesn't terminate then kill -9 will almost certainly leave orphans.

To force kill them you need to force kill the script and force kill all it's children. This is generally messy and not recommended as an automated action.

Luckily timeout is aware of the issue of child processes and wipes out the entire process tree if asked to.

timeout -s 9 20 myscript

Will force kill all child processes. Be aware this is still a "dirty" way to close commands as they have no chance to clean themselves up properly and can corrupt files.

  • Is there a way to first try the 'clean' timeout, and if it does not work, use the 'dirty' way? For example timeout -s 9 2 timeout 1 myscript - after 1 second kill with sigterm, after 2 seconds kill with -9. Will this work? – Erel Segal-Halevi Mar 11 at 14:14
  • Yes that should work. As you guess the outer timeout will intervene 1 second after the inner (softer) one tries. – Philip Couling Mar 11 at 14:32

The -s option of the timeout command allows you to specify the signal to be sent on timeout.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.