system call that is killed after n seconds if not finished

Adam Skutt askutt at gmail.com
Tue Apr 17 09:22:13 EDT 2012


On Apr 16, 11:34 am, Alain Ketterlin <al... at dpt-info.u-strasbg.fr>
wrote:
> Jaroslav Dobrek <jaroslav.dob... at gmail.com> writes:
> > I would like to execute shell commands, but only if their execution
> > time is not longer than n seconds. Like so:
>
> > monitor(os.system("do_something"), 5)
>
> > I.e. the command do_somthing should be executed by the operating
> > system. If the call has not finished after 5 seconds, the process
> > should be killed.
>
> > How could this be done?
>
> My system (linux) has a timeout command that does just this.

Alas, while timeout(1) is in GNU coreutils it's a rather recent
addition and so you cannot rely on it being on every Linux machine.
Also, there are multiple versions of timeout, from different
applications, that do the same thing with different syntax.  However,
if it is available on the systems you care about, I would use it.
Pay close attention to its caveats.

> Otherwise,
> you may use subprocess.Popen to spawn the process, sleep for 5 seconds
> in the parent, then use Popen.poll() to check whether the process has
> finished, and finally Popen.kill() if it has not.
>

That's true subject to two conditions:
1. The subprocess doesn't spawn child processes of its own or you
don't care about killing them (doubtful).
2. The application isn't running on a command-line, where it could be
suspended; or you don't care about timeliness if the application is
suspended.

The first item can be solved by manually performing fork()/exec() and
using setpgid() to create a process group.  Terminating the process
group on timeout will terminate the subprocess and all of its
children.

The second one is much more tricky to solve.  Basically, you have to
supply enough job control functionality (like a shell) to handle the
terminal signals and ensure your signaling process stays alive.  The
GNU coreutils version of timeout basically immunizes itself from the
signals, which works but also creates problems if it is run in the
background.  If you need to do this, I'd advise cheating, as I believe
the general solution is pretty ugly and doesn't exist in ready form.
I certainly could not find it.

Adam



More information about the Python-list mailing list