110898Sroland.mainz@nrubsig.org# 210898Sroland.mainz@nrubsig.org# CDDL HEADER START 310898Sroland.mainz@nrubsig.org# 410898Sroland.mainz@nrubsig.org# The contents of this file are subject to the terms of the 510898Sroland.mainz@nrubsig.org# Common Development and Distribution License (the "License"). 610898Sroland.mainz@nrubsig.org# You may not use this file except in compliance with the License. 710898Sroland.mainz@nrubsig.org# 810898Sroland.mainz@nrubsig.org# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 910898Sroland.mainz@nrubsig.org# or http://www.opensolaris.org/os/licensing. 1010898Sroland.mainz@nrubsig.org# See the License for the specific language governing permissions 1110898Sroland.mainz@nrubsig.org# and limitations under the License. 1210898Sroland.mainz@nrubsig.org# 1310898Sroland.mainz@nrubsig.org# When distributing Covered Code, include this CDDL HEADER in each 1410898Sroland.mainz@nrubsig.org# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1510898Sroland.mainz@nrubsig.org# If applicable, add the following below this CDDL HEADER, with the 1610898Sroland.mainz@nrubsig.org# fields enclosed by brackets "[]" replaced with your own identifying 1710898Sroland.mainz@nrubsig.org# information: Portions Copyright [yyyy] [name of copyright owner] 1810898Sroland.mainz@nrubsig.org# 1910898Sroland.mainz@nrubsig.org# CDDL HEADER END 2010898Sroland.mainz@nrubsig.org# 2110898Sroland.mainz@nrubsig.org 2210898Sroland.mainz@nrubsig.org# 23*12068SRoger.Faulkner@Oracle.COM# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 2410898Sroland.mainz@nrubsig.org# 2510898Sroland.mainz@nrubsig.org 2610898Sroland.mainz@nrubsig.org# 2710898Sroland.mainz@nrubsig.org# Written by Roland Mainz <roland.mainz@nrubsig.org> 2810898Sroland.mainz@nrubsig.org# 2910898Sroland.mainz@nrubsig.org 3010898Sroland.mainz@nrubsig.org# test setup 3110898Sroland.mainz@nrubsig.orgfunction err_exit 3210898Sroland.mainz@nrubsig.org{ 3310898Sroland.mainz@nrubsig.org print -u2 -n "\t" 3410898Sroland.mainz@nrubsig.org print -u2 -r ${Command}[$1]: "${@:2}" 35*12068SRoger.Faulkner@Oracle.COM (( Errors < 127 && Errors++ )) 3610898Sroland.mainz@nrubsig.org} 3710898Sroland.mainz@nrubsig.orgalias err_exit='err_exit $LINENO' 3810898Sroland.mainz@nrubsig.org 3910898Sroland.mainz@nrubsig.orgset -o nounset 4010898Sroland.mainz@nrubsig.orgCommand=${0##*/} 4110898Sroland.mainz@nrubsig.orginteger Errors=0 4210898Sroland.mainz@nrubsig.org 4310898Sroland.mainz@nrubsig.org 4410898Sroland.mainz@nrubsig.orgfunction isvalidpid 4510898Sroland.mainz@nrubsig.org{ 4610898Sroland.mainz@nrubsig.org kill -0 ${1} 2>/dev/null && return 0 4710898Sroland.mainz@nrubsig.org return 1 4810898Sroland.mainz@nrubsig.org} 4910898Sroland.mainz@nrubsig.orginteger testfilesize i maxwait 5010898Sroland.mainz@nrubsig.orgtypeset tmpfile 5110898Sroland.mainz@nrubsig.orginteger testid 5210898Sroland.mainz@nrubsig.org 5310898Sroland.mainz@nrubsig.org 5410898Sroland.mainz@nrubsig.org######################################################################## 5510898Sroland.mainz@nrubsig.org#### test set 001: 5610898Sroland.mainz@nrubsig.org# run loop and check various temp filesizes 5710898Sroland.mainz@nrubsig.org# (Please keep this test syncted with sun_solaris_cr_6800929_large_command_substitution_hang.sh) 5810898Sroland.mainz@nrubsig.org 5910898Sroland.mainz@nrubsig.org# test 1: run loop and check various temp filesizes 60*12068SRoger.Faulkner@Oracle.COMtmpfile="$(mktemp -t "ksh93_tests_command_substitution.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file." 6110898Sroland.mainz@nrubsig.org 6210898Sroland.mainz@nrubsig.orgcompound test1=( 6310898Sroland.mainz@nrubsig.org compound -a testcases=( 6410898Sroland.mainz@nrubsig.org # test 1a: Run test child for $(...) 6510898Sroland.mainz@nrubsig.org # (note the pipe chain has to end in a builtin command, an external command may not trigger the bug) 6610898Sroland.mainz@nrubsig.org ( name="test1a" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" ) 6710898Sroland.mainz@nrubsig.org # test 1b: Same as test1a but uses ${... ; } instead if $(...) 6810898Sroland.mainz@nrubsig.org ( name="test1b" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" ) 6910898Sroland.mainz@nrubsig.org # test 1c: Same as test1a but does not use a pipe 7010898Sroland.mainz@nrubsig.org ( name="test1c" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" ) 7110898Sroland.mainz@nrubsig.org # test 1d: Same as test1a but does not use a pipe 7210898Sroland.mainz@nrubsig.org ( name="test1d" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" ) 7310898Sroland.mainz@nrubsig.org 7410898Sroland.mainz@nrubsig.org # test 1e: Same as test1a but uses an external "cat" command 7510898Sroland.mainz@nrubsig.org ( name="test1e" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" ) 7610898Sroland.mainz@nrubsig.org # test 1f: Same as test1a but uses an external "cat" command 7710898Sroland.mainz@nrubsig.org ( name="test1f" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" ) 7810898Sroland.mainz@nrubsig.org # test 1g: Same as test1a but uses an external "cat" command 7910898Sroland.mainz@nrubsig.org ( name="test1g" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" ) 8010898Sroland.mainz@nrubsig.org # test 1h: Same as test1a but uses an external "cat" command 8110898Sroland.mainz@nrubsig.org ( name="test1h" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" ) 8210898Sroland.mainz@nrubsig.org ) 8310898Sroland.mainz@nrubsig.org) 8410898Sroland.mainz@nrubsig.org 8510898Sroland.mainz@nrubsig.orgfor (( testfilesize=1*1024 ; testfilesize <= 1024*1024 ; testfilesize*=2 )) ; do 8610898Sroland.mainz@nrubsig.org # Create temp file 8710898Sroland.mainz@nrubsig.org { 8810898Sroland.mainz@nrubsig.org for (( i=0 ; i < testfilesize ; i+=64 )) ; do 8910898Sroland.mainz@nrubsig.org print "0123456789abcdef01234567890ABCDEF0123456789abcdef01234567890ABCDE" 9010898Sroland.mainz@nrubsig.org done 9110898Sroland.mainz@nrubsig.org } >"${tmpfile}" 9210898Sroland.mainz@nrubsig.org 9310898Sroland.mainz@nrubsig.org # wait up to log2(i) seconds for the child to terminate 9410898Sroland.mainz@nrubsig.org # (this is 10 seconds for 1KB and 19 seconds for 512KB) 9510898Sroland.mainz@nrubsig.org (( maxwait=log2(testfilesize) )) 9610898Sroland.mainz@nrubsig.org 9710898Sroland.mainz@nrubsig.org for testid in "${!test1.testcases[@]}" ; do 9810898Sroland.mainz@nrubsig.org nameref currtst=test1.testcases[testid] 9910898Sroland.mainz@nrubsig.org ${SHELL} -o errexit -c "${currtst.cmd}" >"${tmpfile}.out" & 10010898Sroland.mainz@nrubsig.org (( childpid=$! )) 10110898Sroland.mainz@nrubsig.org 10210898Sroland.mainz@nrubsig.org for (( i=0 ; i < maxwait ; i++ )) ; do 10310898Sroland.mainz@nrubsig.org isvalidpid ${childpid} || break 10410898Sroland.mainz@nrubsig.org sleep 0.25 10510898Sroland.mainz@nrubsig.org done 10610898Sroland.mainz@nrubsig.org 10710898Sroland.mainz@nrubsig.org if isvalidpid ${childpid} ; then 10810898Sroland.mainz@nrubsig.org err_exit "${currtst.name}: child (pid=${childpid}) still busy, filesize=${testfilesize}." 10910898Sroland.mainz@nrubsig.org kill -KILL ${childpid} 2>/dev/null 11010898Sroland.mainz@nrubsig.org fi 11110898Sroland.mainz@nrubsig.org wait || err_exit "${currtst.name}: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 11210898Sroland.mainz@nrubsig.org 11310898Sroland.mainz@nrubsig.org # compare input/output 11410898Sroland.mainz@nrubsig.org cmp -s "${tmpfile}" "${tmpfile}.out" || err_exit "${currtst.name}: ${tmpfile} and ${tmpfile}.out differ, filesize=${testfilesize}." 11510898Sroland.mainz@nrubsig.org rm "${tmpfile}.out" 11610898Sroland.mainz@nrubsig.org done 11710898Sroland.mainz@nrubsig.org 11810898Sroland.mainz@nrubsig.org # Cleanup 11910898Sroland.mainz@nrubsig.org rm "${tmpfile}" 12010898Sroland.mainz@nrubsig.orgdone 12110898Sroland.mainz@nrubsig.org 12210898Sroland.mainz@nrubsig.org 12310898Sroland.mainz@nrubsig.org######################################################################## 12410898Sroland.mainz@nrubsig.org#### test set 002: 12510898Sroland.mainz@nrubsig.org# If a command substitution calls a function and that function contains 12610898Sroland.mainz@nrubsig.org# a command substitution which contains a piped command, the original 12710898Sroland.mainz@nrubsig.org# command substitution calling the function will return 127 instead of 0. 12810898Sroland.mainz@nrubsig.org# This is causing problems in several VSC tests. 12910898Sroland.mainz@nrubsig.org# If we remove the piped command from the simple 13010898Sroland.mainz@nrubsig.org# case in the attached script, it returns 0. 13110898Sroland.mainz@nrubsig.org 13210898Sroland.mainz@nrubsig.orgtypeset str 13310898Sroland.mainz@nrubsig.orgtypeset testbody 13410898Sroland.mainz@nrubsig.orgtypeset testout 13510898Sroland.mainz@nrubsig.org 13610898Sroland.mainz@nrubsig.orgtestbody=$( 13710898Sroland.mainz@nrubsig.org# <CS> means command substitution start, <CE> means command substitution end 13810898Sroland.mainz@nrubsig.orgcat <<EOF 13910898Sroland.mainz@nrubsig.orgmyfunc () 14010898Sroland.mainz@nrubsig.org{ 14110898Sroland.mainz@nrubsig.org pipedcmd=<CS> printf "hi" | tr "h" "H" <CE> 14210898Sroland.mainz@nrubsig.org echo \$pipedcmd 14310898Sroland.mainz@nrubsig.org 14410898Sroland.mainz@nrubsig.org return 0 14510898Sroland.mainz@nrubsig.org} 14610898Sroland.mainz@nrubsig.org 14710898Sroland.mainz@nrubsig.orgfoo=<CS>myfunc<CE> 14810898Sroland.mainz@nrubsig.orgretval=\$? 14910898Sroland.mainz@nrubsig.org 15010898Sroland.mainz@nrubsig.orgif [ "\$foo"X != "HiX" ]; then 15110898Sroland.mainz@nrubsig.org echo "myfunc returned '\${foo}'; expected 'Hi'" 15210898Sroland.mainz@nrubsig.orgfi 15310898Sroland.mainz@nrubsig.org 15410898Sroland.mainz@nrubsig.orgif [ \$retval -ne 0 ]; then 15510898Sroland.mainz@nrubsig.org echo "command substitution calling myfunc returned \"\${retval}\"; expected 0" 15610898Sroland.mainz@nrubsig.orgelse 15710898Sroland.mainz@nrubsig.org echo "command substitution calling myfunc successfully returned 0" 15810898Sroland.mainz@nrubsig.orgfi 15910898Sroland.mainz@nrubsig.orgEOF 16010898Sroland.mainz@nrubsig.org) 16110898Sroland.mainz@nrubsig.org 16210898Sroland.mainz@nrubsig.org 16310898Sroland.mainz@nrubsig.org# Test 002/a: Plain test 16410898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/$(/g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 16510898Sroland.mainz@nrubsig.org[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}" 16610898Sroland.mainz@nrubsig.org 16710898Sroland.mainz@nrubsig.org# Test 002/b: Same as test002/a but replaces "$(" with "${" 16810898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/${ /g;s/<CE>/ ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 16910898Sroland.mainz@nrubsig.org[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}" 17010898Sroland.mainz@nrubsig.org 17110898Sroland.mainz@nrubsig.org# Test 002/c: Same as test002/a but forces |fork()| for a subshell via "ulimit -c 0" 17210898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/$( ulimit -c 0 ; /g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 17310898Sroland.mainz@nrubsig.org[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}" 17410898Sroland.mainz@nrubsig.org 17510898Sroland.mainz@nrubsig.org# Test 002/d: Same as test002/a but uses extra subshell 17610898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/$( ( /g;s/<CE>/) )/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 17710898Sroland.mainz@nrubsig.org[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}" 17810898Sroland.mainz@nrubsig.org 17910898Sroland.mainz@nrubsig.org# Test 002/e: Same as test002/b but uses extra subshell after "${ " 18010898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/${ ( /g;s/<CE>/) ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 18110898Sroland.mainz@nrubsig.org[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}" 18210898Sroland.mainz@nrubsig.org 18310898Sroland.mainz@nrubsig.org 18410898Sroland.mainz@nrubsig.org 18510898Sroland.mainz@nrubsig.org 18610898Sroland.mainz@nrubsig.org######################################################################## 18710898Sroland.mainz@nrubsig.org#### test set 003: 18810898Sroland.mainz@nrubsig.org# An expression within backticks which should return false, instead 18910898Sroland.mainz@nrubsig.org# returns true (0). 19010898Sroland.mainz@nrubsig.org 19110898Sroland.mainz@nrubsig.orgtypeset str 19210898Sroland.mainz@nrubsig.orgtypeset testbody 19310898Sroland.mainz@nrubsig.orgtypeset testout 19410898Sroland.mainz@nrubsig.org 19510898Sroland.mainz@nrubsig.orgtestbody=$( 19610898Sroland.mainz@nrubsig.org# <CS> means command substitution start, <CE> means command substitution end 19710898Sroland.mainz@nrubsig.orgcat <<EOF 19810898Sroland.mainz@nrubsig.orgif <CS>expr "NOMATCH" : ".*Z" > /dev/null<CE> ; then 19910898Sroland.mainz@nrubsig.org echo "xerror" 20010898Sroland.mainz@nrubsig.orgelse 20110898Sroland.mainz@nrubsig.org echo "xok" 20210898Sroland.mainz@nrubsig.orgfi 20310898Sroland.mainz@nrubsig.orgEOF 20410898Sroland.mainz@nrubsig.org) 20510898Sroland.mainz@nrubsig.org 20610898Sroland.mainz@nrubsig.org 20710898Sroland.mainz@nrubsig.org# Test 003/a: Plain test 20810898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/$(/g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 20910898Sroland.mainz@nrubsig.org[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}" 21010898Sroland.mainz@nrubsig.org 21110898Sroland.mainz@nrubsig.org# Test 003/b: Same as test003/a but replaces "$(" with "${" 21210898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/${ /g;s/<CE>/ ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 21310898Sroland.mainz@nrubsig.org[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}" 21410898Sroland.mainz@nrubsig.org 21510898Sroland.mainz@nrubsig.org# Test 003/c: Same as test003/a but forces |fork()| for a subshell via "ulimit -c 0" 21610898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/$( ulimit -c 0 ; /g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 21710898Sroland.mainz@nrubsig.org[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}" 21810898Sroland.mainz@nrubsig.org 21910898Sroland.mainz@nrubsig.org# Test 003/d: Same as test003/a but uses extra subshell 22010898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/$( ( /g;s/<CE>/) )/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 22110898Sroland.mainz@nrubsig.org[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}" 22210898Sroland.mainz@nrubsig.org 22310898Sroland.mainz@nrubsig.org# Test 003/e: Same as test003/b but uses extra subshell after "${ " 22410898Sroland.mainz@nrubsig.orgtestout=${ printf "%B\n" testbody | sed 's/<CS>/${ ( /g;s/<CE>/) ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" } 22510898Sroland.mainz@nrubsig.org[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}" 22610898Sroland.mainz@nrubsig.org 22710898Sroland.mainz@nrubsig.org 22810898Sroland.mainz@nrubsig.org######################################################################## 22910898Sroland.mainz@nrubsig.org#### test set 004: 23010898Sroland.mainz@nrubsig.org# test pipe within ${... ; } command subtitution ending in a 23110898Sroland.mainz@nrubsig.org# non-builtin command (therefore we use "/bin/cat" instead of "cat" below 23210898Sroland.mainz@nrubsig.org# to force the use of the external "cat" command). ast-ksh.2009-01-20 23310898Sroland.mainz@nrubsig.org# had a bug which caused this test to fail. 23410898Sroland.mainz@nrubsig.orgtestout=$( ${SHELL} -c 'pipedcmd=${ printf "hi" | /bin/cat ; } ; print $pipedcmd' ) 23510898Sroland.mainz@nrubsig.org[[ "${testout}" == "hi" ]] || err_exit "test004: Expected 'hi', got '${testout}'" 23610898Sroland.mainz@nrubsig.org 23710898Sroland.mainz@nrubsig.org 23810898Sroland.mainz@nrubsig.org######################################################################## 23910898Sroland.mainz@nrubsig.org#### test set 005: 24010898Sroland.mainz@nrubsig.org# Test whether the shell may hang in a 24110898Sroland.mainz@nrubsig.org# 'exec 5>/dev/null; print $(eval ls -d . 2>&1 1>&5)' 24210898Sroland.mainz@nrubsig.org# Originally discovered with ast-ksh.2009-05-05 which hung in 24310898Sroland.mainz@nrubsig.org# the "configure" script of postgresql-8.3.7.tar.gz (e.g. 24410898Sroland.mainz@nrubsig.org# configure --enable-thread-safety --without-readline) 24510898Sroland.mainz@nrubsig.orgcompound test5=( 24610898Sroland.mainz@nrubsig.org compound -a testcases=( 24710898Sroland.mainz@nrubsig.org # gsf's reduced testcase 24810898Sroland.mainz@nrubsig.org ( name="test5_a" cmd='exec 5>/dev/null; print $(eval ls -d . 2>&1 1>&5)done' ) 24910898Sroland.mainz@nrubsig.org # gisburn's reduced testcase 25010898Sroland.mainz@nrubsig.org ( name="test5_b" cmd='exec 5>/dev/null; print $(eval "/bin/printf hello\n" 2>&1 1>&5)done' ) 25110898Sroland.mainz@nrubsig.org 25210898Sroland.mainz@nrubsig.org ## The following tests do not trigger the problem but are included here for completeness 25310898Sroland.mainz@nrubsig.org ## and to make sure we don't get other incarnations of the same problem later... 25410898Sroland.mainz@nrubsig.org 25510898Sroland.mainz@nrubsig.org # same as test5_a but uses ${ ... ; } instead of $(...) 25610898Sroland.mainz@nrubsig.org ( name="test5_c" cmd='exec 5>/dev/null; print "${ eval ls -d . 2>&1 1>&5 ;}done"' ) 25710898Sroland.mainz@nrubsig.org # same as test5_b but uses ${ ... ; } instead of $(...) 25810898Sroland.mainz@nrubsig.org ( name="test5_d" cmd='exec 5>/dev/null; print "${ eval "/bin/printf hello\n" 2>&1 1>&5 ;}done"' ) 25910898Sroland.mainz@nrubsig.org # same as test5_a but uses "ulimit -c 0" to force the shell to use a seperare process for $(...) 26010898Sroland.mainz@nrubsig.org ( name="test5_e" cmd='exec 5>/dev/null; print $(ulimit -c 0 ; eval ls -d . 2>&1 1>&5)done' ) 26110898Sroland.mainz@nrubsig.org # same as test5_b but uses "ulimit -c 0" to force the shell to use a seperare process for $(...) 26210898Sroland.mainz@nrubsig.org ( name="test5_f" cmd='exec 5>/dev/null; print $(ulimit -c 0 ; eval "/bin/printf hello\n" 2>&1 1>&5)done' ) 26310898Sroland.mainz@nrubsig.org ) 26410898Sroland.mainz@nrubsig.org) 26510898Sroland.mainz@nrubsig.org 26610898Sroland.mainz@nrubsig.orgmaxwait=5 26710898Sroland.mainz@nrubsig.orgfor testid in "${!test5.testcases[@]}" ; do 26810898Sroland.mainz@nrubsig.org nameref currtst=test5.testcases[testid] 26910898Sroland.mainz@nrubsig.org ${SHELL} -o errexit -c "${currtst.cmd}" >"${tmpfile}.out" & 27010898Sroland.mainz@nrubsig.org (( childpid=$! )) 27110898Sroland.mainz@nrubsig.org 27210898Sroland.mainz@nrubsig.org for (( i=0 ; i < maxwait ; i++ )) ; do 27310898Sroland.mainz@nrubsig.org isvalidpid ${childpid} || break 27410898Sroland.mainz@nrubsig.org sleep 0.25 27510898Sroland.mainz@nrubsig.org done 27610898Sroland.mainz@nrubsig.org 27710898Sroland.mainz@nrubsig.org if isvalidpid ${childpid} ; then 27810898Sroland.mainz@nrubsig.org err_exit "${currtst.name}: child (pid=${childpid}) still busy." 27910898Sroland.mainz@nrubsig.org kill -KILL ${childpid} 2>/dev/null 28010898Sroland.mainz@nrubsig.org fi 28110898Sroland.mainz@nrubsig.org wait || err_exit "${currtst.name}: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 28210898Sroland.mainz@nrubsig.org 28310898Sroland.mainz@nrubsig.org testout="$( < "${tmpfile}.out")" 28410898Sroland.mainz@nrubsig.org rm "${tmpfile}.out" || err_exit "File '${tmpfile}.out' could not be removed." 28510898Sroland.mainz@nrubsig.org [[ "${testout}" == "done" ]] || err_exit "test '${currtst.name}' failed, expected 'done', got '${testout}'" 28610898Sroland.mainz@nrubsig.orgdone 28710898Sroland.mainz@nrubsig.org 28810898Sroland.mainz@nrubsig.org 28910898Sroland.mainz@nrubsig.org# tests done 29010898Sroland.mainz@nrubsig.orgexit $((Errors)) 291