Add a trivial script to extract the times from *.report.txt files.
[llvm-testsuite.git] / RunSafely.sh
blob073d7495417cb35914363c8405f59a0aaf3d15bd
1 #!/bin/sh
3 # Program: RunSafely.sh
5 # Synopsis: This script simply runs another program. If the program works
6 # correctly, this script has no effect, otherwise it will do things
7 # like print a stack trace of a core dump. It always returns
8 # "successful" so that tests will continue to be run.
10 # This script funnels stdout and stderr from the program into the
11 # fourth argument specified, and outputs a <outfile>.time file which
12 # contains a timing of the program and the program's exit code.
14 # The <exitok> parameter specifies how the program's exit status
15 # is interpreted. If the <exitok> parameter is non-zero, any
16 # non-zero exit status from the program is considered to indicate
17 # a test failure. If the <exitok> parameter is zero, only exit
18 # statuses that indicates that the program could not be executed
19 # normally or that the program was terminated as a signal are
20 # considered to indicate a test failure.
22 # If optional parameters -r <remote host> -l <remote user> are
23 # specified, it execute the program remotely using rsh.
25 # Syntax:
27 # RunSafely.sh [-r <rhost>] [-l <ruser>] [-rc <client>] [-rp <port>]
28 # [-u <under>]
29 # <timeout> <exitok> <infile> <outfile> <program> <args...>
31 # where:
32 # <rhost> is the remote host to execute the program
33 # <ruser> is the username on the remote host
34 # <client> is the remote client used to execute the program
35 # <port> is the port used by the remote client
36 # <under> is a wrapper that the program is run under
37 # <timeout> is the maximum number of seconds to let the <program> run
38 # <exitok> is 1 if the program must exit with 0 return code
39 # <infile> is a file from which standard input is directed
40 # <outfile> is a file to which standard output and error are directed
41 # <program> is the path to the program to run
42 # <args...> are the arguments to pass to the program.
44 if [ $# -lt 4 ]; then
45 echo "./RunSafely.sh <timeout> <exitok> <infile> <outfile> <program> <args...>"
46 exit 1
49 # Save a copy of the original arguments in a string before we
50 # clobber them with the shift command.
51 ORIG_ARGS="$*"
53 DIR=${0%%`basename $0`}
55 RHOST=
56 RUSER=`id -un`
57 RCLIENT=rsh
58 RPORT=
59 RUN_UNDER=
60 TIMEIT=time
61 if [ $1 = "-r" ]; then
62 RHOST=$2
63 shift 2
65 if [ $1 = "-l" ]; then
66 RUSER=$2
67 shift 2
69 if [ $1 = "-rc" ]; then
70 RCLIENT=$2
71 shift 2
73 if [ $1 = "-rp" ]; then
74 RPORT="-p $2"
75 shift 2
77 if [ $1 = "-u" ]; then
78 RUN_UNDER=$2
79 shift 2
81 if [ $1 = "-t" ]; then
82 TIMEIT=$2
83 shift 2
86 ULIMIT=$1
87 EXITOK=$2
88 INFILE=$3
89 OUTFILE=$4
90 PROGRAM=$5
91 shift 5
92 SYSTEM=`uname -s`
94 PROG=${PROGRAM}
95 if [ `basename ${PROGRAM}` = "lli" ]; then
96 PROG=`basename ${PROGRAM}`
99 ULIMITCMD=""
100 case $SYSTEM in
101 CYGWIN*)
103 Darwin*)
104 # Disable core file emission, the script doesn't find it anyway because it
105 # is put into /cores.
106 ULIMITCMD="$ULIMITCMD ulimit -c 0;"
107 ULIMITCMD="$ULIMITCMD ulimit -t $ULIMIT;"
108 # To prevent infinite loops which fill up the disk, specify a limit on size
109 # of files being output by the tests. 10 MB should be enough for anybody. ;)
110 ULIMITCMD="$ULIMITCMD ulimit -f 10485760;"
113 ULIMITCMD="$ULIMITCMD ulimit -t $ULIMIT;"
114 ULIMITCMD="$ULIMITCMD ulimit -c unlimited;"
115 # To prevent infinite loops which fill up the disk, specify a limit on size
116 # of files being output by the tests. 10 MB should be enough for anybody. ;)
117 ULIMITCMD="$ULIMITCMD ulimit -f 10485760;"
119 # virtual memory: 400 MB should be enough for anybody. ;)
120 ULIMITCMD="$ULIMITCMD ulimit -v 400000;"
121 esac
122 rm -f core core.*
125 # Run the command, timing its execution.
126 # The standard output and standard error of $PROGRAM should go in $OUTFILE,
127 # and the standard error of time should go in $OUTFILE.time. Note that the
128 # return code of the program is appended to the $OUTFILE on an "Exit Val ="
129 # line.
131 # To get the time program and the specified program different output filenames,
132 # we tell time to launch a shell which in turn executes $PROGRAM with the
133 # necessary I/O redirection.
135 PWD=`pwd`
136 COMMAND="$RUN_UNDER $PROGRAM $*"
137 COMMAND="${DIR}TimedExec.sh $ULIMIT $PWD $COMMAND"
138 COMMAND=$(echo "$COMMAND" | sed -e 's#"#\\"#g')
140 if [ "x$RHOST" = x ] ; then
141 ( sh -c "$ULIMITCMD $TIMEIT -p sh -c '$COMMAND >$OUTFILE 2>&1 < $INFILE; echo exit \$?'" ) 2>&1 \
142 | awk -- '\
143 BEGIN { cpu = 0.0; }
144 /^user/ { cpu += $2; print; }
145 !/^user/ { print; }
146 END { printf("program %f\n", cpu); }' > $OUTFILE.time
147 else
148 rm -f "$PWD/${PROG}.command"
149 rm -f "$PWD/${PROG}.remote"
150 rm -f "$PWD/${PROG}.remote.time"
151 echo "$ULIMITCMD cd $PWD; ($TIMEIT -p ($COMMAND > $PWD/${OUTFILE}.remote 2>&1 < $INFILE;); echo exit \$?) > $PWD/${OUTFILE}.remote.time 2>&1" > "$PWD/${PROG}.command"
152 chmod +x "$PWD/${PROG}.command"
154 ( $RCLIENT -l $RUSER $RHOST $RPORT "ls $PWD/${PROG}.command" ) > /dev/null 2>&1
155 ( $RCLIENT -l $RUSER $RHOST $RPORT "$PWD/${PROG}.command" )
156 cat $PWD/${OUTFILE}.remote.time | awk -- '\
157 BEGIN { cpu = 0.0; }
158 /^user/ { cpu += $2; print; }
159 !/^user/ { print; }
160 END { printf("program %f\n", cpu); }' > $OUTFILE.time
161 sleep 1
162 cp -f $PWD/${OUTFILE}.remote ${OUTFILE}
163 rm -f $PWD/${OUTFILE}.remote
164 rm -f $PWD/${OUTFILE}.remote.time
167 exitval=`grep '^exit ' $OUTFILE.time | sed -e 's/^exit //'`
168 fail=yes
169 if [ -z "$exitval" ] ; then
170 exitval=99
171 echo "TEST $PROGRAM FAILED: CAN'T GET EXIT CODE!"
172 elif test "$exitval" -eq 126 ; then
173 echo "TEST $PROGRAM FAILED: command not executable (exit status 126)!"
174 elif test "$exitval" -eq 127 ; then
175 echo "TEST $PROGRAM FAILED: command not found (exit status 127)!"
176 elif test "$exitval" -eq 128 ; then
177 # Exit status 128 doesn't have a standard meaning, but it's unlikely
178 # to be expected program behavior.
179 echo "TEST $PROGRAM FAILED: exit status 128!"
180 elif test "$exitval" -gt 128 ; then
181 echo "TEST $PROGRAM FAILED: process terminated by signal (exit status $exitval)!"
182 elif [ "$EXITOK" -ne 0 -a "$exitval" -ne 0 ] ; then
183 echo "TEST $PROGRAM FAILED: EXIT != 0"
184 else
185 fail=no
187 echo "exit $exitval" >> $OUTFILE
189 # If we detected a failure, print the name of the test executable to the
190 # output file. This will cause it to compare as different with other runs
191 # of the same test even if they fail in the same way, because they'll have
192 # different command names.
193 if [ "${fail}" != "no" ]; then
194 echo "RunSafely.sh detected a failure with these command-line arguments: " \
195 "$ORIG_ARGS" >> $OUTFILE
198 if ls | egrep "^core" > /dev/null
199 then
200 # If we are on a sun4u machine (UltraSparc), then the code we're generating
201 # is 64 bit code. In that case, use gdb-64 instead of gdb.
202 myarch=`uname -m`
203 if [ "$myarch" = "sun4u" ]
204 then
205 GDB="gdb-64"
206 else
207 GDB=gdb
210 corefile=`ls core* | head -n 1`
211 echo "where 100" > StackTrace.$$
212 $GDB -q -batch --command=StackTrace.$$ --core=$corefile $PROGRAM < /dev/null
213 rm -f StackTrace.$$ $corefile
215 # Always return "successful" so that tests will continue to be run.
216 exit 0