1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

95 lines
2.6 KiB
Bash
Executable File

#!/bin/bash
# time-and-mem-limit
# Ralph Becket <rafe@csse.unimelb.edu.au>
# Tue Feb 10 12:21:58 EST 2009
#
# usage: time-and-mem-limit N M cmd ...
#
# Kill cmd ... if it does not terminate after N seconds of wallclock time or if
# it uses more than M megabytes of memory. Either "EXCEEDED TIME LIMIT" or
# "EXCEEDED MEMORY LIMIT" is printed on stderr as appropriate if cmd ... is
# killed for one of these reasons.
USAGE="usage: time-and-mem-limit num-seconds num-megabytes cmd ..."
if [ "$*" = "-h" -o "$*" = "--help" ]
then
echo $USAGE >&2
exit 0
fi
if [ $# -lt 3 ]
then
echo $USAGE >&2
exit 1
fi
# CMDPID: we exec the command so it gets the current PID.
CMDPID=$$
# TIMELIMIT: the time limit in seconds.
TIMELIMIT=$1
# MEMLIMIT: the memory limit in megabytes.
MEMLIMITMB=$2
MEMLIMITKB=$(($MEMLIMITMB << 10))
shift 2
# CMD: anything else on the command line is the command to be executed.
CMD=$@
declare TimeoutOrig=$(ulimit -t)
declare MemoryOrig=$(ulimit -v)
# Using ulimit like this doesn't work on Cygwin.
#
if test ! -e /bin/cygpath.exe
then
ulimit -S -t ${TIMELIMIT}
ulimit -S -v ${MEMLIMITKB}
else ### Only on Cygwin: Ubuntu 15 does not allow to delete output files and reports wrong exit result
# Check the time and memory limits every ten seconds in a background
# process. If either limit is reached, kill the process.
(
for (( i=0 ; i<$TIMELIMIT ; i+=1 ))
do
# Sleep for 1 seconds.
sleep 1
# Obtain the process memory usage in kilobytes.
# (We use this form of ps arguments for portability).
CMDMEMUSAGEKB=`ps -p $CMDPID -o vsize=""`
# Quit if the process has already terminated.
if [ -z $CMDMEMUSAGEKB ]
then
exit 0
fi
# Kill the process if it has exceeded its memory limit.
if [ $CMDMEMUSAGEKB -gt $MEMLIMITKB ]
then
kill -KILL $CMDPID >/dev/null 2>&1
echo "" >&2
echo "EXCEEDED MEMORY LIMIT OF $MEMLIMITMB Mbytes" >&2
exit 1
fi
done
# Kill the process if it has exceeded its time limit.
if ps -p $CMDPID >/dev/null 2>&1
then
kill -KILL $CMDPID >/dev/null 2>&1
echo "" >&2
echo "EXCEEDED TIME LIMIT OF $TIMELIMIT s" >&2
exit 1
fi
) &
# The background process above sometimes does not seem to fire or does not
# kill all subprocesses. "ulimit" is more reliable, but it is not clear how
# to get useful, specific error messages. Thus for now we use both methods.
fi
# Run the command.
exec $CMD
if test ! -e /bin/cygpath.exe
then
ulimit -S -t ${TimeoutOrig}
ulimit -S -v ${MemoryOrig}
fi