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.
27 # RunSafely.sh [-r <rhost>] [-l <ruser>] [-rc <client>] [-rp <port>]
29 # <timeout> <exitok> <infile> <outfile> <program> <args...>
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.
45 echo "./RunSafely.sh <timeout> <exitok> <infile> <outfile> <program> <args...>"
49 # Save a copy of the original arguments in a string before we
50 # clobber them with the shift command.
53 DIR
=${0%%`basename $0`}
61 if [ $1 = "-r" ]; then
65 if [ $1 = "-l" ]; then
69 if [ $1 = "-rc" ]; then
73 if [ $1 = "-rp" ]; then
77 if [ $1 = "-u" ]; then
81 if [ $1 = "-t" ]; then
95 if [ `basename ${PROGRAM}` = "lli" ]; then
96 PROG
=`basename ${PROGRAM}`
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;"
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 ="
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.
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 \
144 /^user/ { cpu += $2; print; }
146 END { printf("program %f\n", cpu); }' > $OUTFILE.
time
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 -- '\
158 /^user/ { cpu += $2; print; }
160 END { printf("program %f\n", cpu); }' > $OUTFILE.
time
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 //'`
169 if [ -z "$exitval" ] ; then
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"
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
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.
203 if [ "$myarch" = "sun4u" ]
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.