# teaching machines

## Limiting Execution Time in a Shell, Part II

A year ago, I thought I worked around the halting problem. I have students’ code that I need to grade, but sometimes they slip in an infinite loop. This really messes up automated grading. I wrote a shell script that would run their code for X seconds, killing their process if necessary. Sadly, I went to use that script again this semester, but it would hang when I invoked it across SSH:

ssh tester@localhost "cd student/folder && forn 30 theirs.exe"

The script works fine when not run across SSH. I don’t know what the problem is. Instead of asking the Internet for help, I just rewrote the script in Ruby, and it works just fine across SSH:

#!/usr/bin/env ruby

# ----------------------------------------------------------------------------
# FILE:   forn
# AUTHOR: Chris Johnson
# DATE:   Dec 03 2014
#
# Executes a command with a time limit. If the command takes longer than the
# specified number of seconds, it is killed and status 37 is returned.
# Otherwise, the exit status of the command is returned.
# ----------------------------------------------------------------------------

require 'timeout'

if ARGV.length < 1
puts "Usage: forn delay-in-seconds command arg1 arg2 ..."
exit 1
end

delay = ARGV[0].to_i
ARGV.shift

# Start command, but kill it if delay elapses.
pid = Process.spawn(ARGV.shelljoin)
begin
Timeout.timeout(delay) do
Process.wait pid
exit \$?.exitstatus
end
rescue Timeout::Error
puts "Uh oh. Execution timed out after #{delay} second#{delay == 1 ? '' : 's'}."
Process.kill(:SIGTERM, pid)
exit 37
end