1*b30d1939SAndy Fiddaman# 2*b30d1939SAndy Fiddaman# CDDL HEADER START 3*b30d1939SAndy Fiddaman# 4*b30d1939SAndy Fiddaman# The contents of this file are subject to the terms of the 5*b30d1939SAndy Fiddaman# Common Development and Distribution License (the "License"). 6*b30d1939SAndy Fiddaman# You may not use this file except in compliance with the License. 7*b30d1939SAndy Fiddaman# 8*b30d1939SAndy Fiddaman# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*b30d1939SAndy Fiddaman# or http://www.opensolaris.org/os/licensing. 10*b30d1939SAndy Fiddaman# See the License for the specific language governing permissions 11*b30d1939SAndy Fiddaman# and limitations under the License. 12*b30d1939SAndy Fiddaman# 13*b30d1939SAndy Fiddaman# When distributing Covered Code, include this CDDL HEADER in each 14*b30d1939SAndy Fiddaman# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*b30d1939SAndy Fiddaman# If applicable, add the following below this CDDL HEADER, with the 16*b30d1939SAndy Fiddaman# fields enclosed by brackets "[]" replaced with your own identifying 17*b30d1939SAndy Fiddaman# information: Portions Copyright [yyyy] [name of copyright owner] 18*b30d1939SAndy Fiddaman# 19*b30d1939SAndy Fiddaman# CDDL HEADER END 20*b30d1939SAndy Fiddaman# 21*b30d1939SAndy Fiddaman 22*b30d1939SAndy Fiddaman# 23*b30d1939SAndy Fiddaman# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24*b30d1939SAndy Fiddaman# 25*b30d1939SAndy Fiddaman 26*b30d1939SAndy Fiddaman# 27*b30d1939SAndy Fiddaman# Test whether CR #6800929 ("snv_106 ksh93 update breaks Install(1M)") has been fixed. 28*b30d1939SAndy Fiddaman# 29*b30d1939SAndy Fiddaman# Quote from CR #6800929: 30*b30d1939SAndy Fiddaman# ---- snip ---- 31*b30d1939SAndy Fiddaman# so i just upgraded this morning from snv_105 to snv_106. now 32*b30d1939SAndy Fiddaman# Install(1M) is hanging whenever i run it. i'm running it as follows: 33*b30d1939SAndy Fiddaman# Install -o debug -k i86xpv -T domu-219:/tmp 34*b30d1939SAndy Fiddaman# 35*b30d1939SAndy Fiddaman# and here's where it's hung: 36*b30d1939SAndy Fiddaman# ---8<--- 37*b30d1939SAndy Fiddaman# Edward Pilatowicz <edward.pilatowicz@sun.com> 38*b30d1939SAndy Fiddaman# $ pstack 204600 39*b30d1939SAndy Fiddaman# 204600: /bin/ksh /opt/onbld/bin/Install -o debug -k i86xpv -T domu-219:/tmp 40*b30d1939SAndy Fiddaman# fffffd7fff2e3d1a write (1, 4154c0, 64) 41*b30d1939SAndy Fiddaman# fffffd7ffefdafc8 sfwr () + 2d0 42*b30d1939SAndy Fiddaman# fffffd7ffefc0f6f _sfflsbuf () + 217 43*b30d1939SAndy Fiddaman# fffffd7ffefcb9f7 sfsync () + 17f 44*b30d1939SAndy Fiddaman# fffffd7ffefc5c58 _sfphead () + 188 45*b30d1939SAndy Fiddaman# fffffd7ffefc5ef5 _sfpmove () + 55 46*b30d1939SAndy Fiddaman# fffffd7ffefc2595 _sfmode () + 22d 47*b30d1939SAndy Fiddaman# fffffd7ffefc5fb1 sfpool () + 99 48*b30d1939SAndy Fiddaman# fffffd7fff15eb8e sh_exec () + 2f56 49*b30d1939SAndy Fiddaman# fffffd7fff15f78c sh_exec () + 3b54 50*b30d1939SAndy Fiddaman# fffffd7fff15d9c8 sh_exec () + 1d90 51*b30d1939SAndy Fiddaman# fffffd7fff15788e sh_subshell () + 646 52*b30d1939SAndy Fiddaman# fffffd7fff134562 comsubst () + 8a2 53*b30d1939SAndy Fiddaman# fffffd7fff12f61f copyto () + bcf 54*b30d1939SAndy Fiddaman# fffffd7fff12df79 sh_macexpand () + 1f1 55*b30d1939SAndy Fiddaman# fffffd7fff1129f5 arg_expand () + a5 56*b30d1939SAndy Fiddaman# fffffd7fff112812 sh_argbuild () + 9a 57*b30d1939SAndy Fiddaman# fffffd7fff15dbe2 sh_exec () + 1faa 58*b30d1939SAndy Fiddaman# fffffd7fff15d854 sh_exec () + 1c1c 59*b30d1939SAndy Fiddaman# fffffd7fff0f22ef b_dot_cmd () + 507 60*b30d1939SAndy Fiddaman# fffffd7fff161559 sh_funct () + 199 61*b30d1939SAndy Fiddaman# fffffd7fff15ef35 sh_exec () + 32fd 62*b30d1939SAndy Fiddaman# fffffd7fff136e86 exfile () + 786 63*b30d1939SAndy Fiddaman# fffffd7fff136676 sh_main () + 7fe 64*b30d1939SAndy Fiddaman# 0000000000400e72 main () + 52 65*b30d1939SAndy Fiddaman# 0000000000400ccc ???? 66*b30d1939SAndy Fiddaman# ---8<--- 67*b30d1939SAndy Fiddaman# 68*b30d1939SAndy Fiddaman# there is only one place where Install(1M) invokes "uniq": 69*b30d1939SAndy Fiddaman# set -- `grep "^CONF" $modlist | sort | uniq`; 70*b30d1939SAndy Fiddaman# 71*b30d1939SAndy Fiddaman# as it turns out, i can easily reproduce this problem as follows: 72*b30d1939SAndy Fiddaman# ---8<--- 73*b30d1939SAndy Fiddaman# $ ksh93 74*b30d1939SAndy Fiddaman# $ set -- `cat /etc/termcap | sort | uniq` 75*b30d1939SAndy Fiddaman# <hang> 76*b30d1939SAndy Fiddaman# ---8<--- 77*b30d1939SAndy Fiddaman# ---- snip ---- 78*b30d1939SAndy Fiddaman 79*b30d1939SAndy Fiddaman 80*b30d1939SAndy Fiddaman# test setup 81*b30d1939SAndy Fiddamanfunction err_exit 82*b30d1939SAndy Fiddaman{ 83*b30d1939SAndy Fiddaman print -u2 -n "\t" 84*b30d1939SAndy Fiddaman print -u2 -r ${Command}[$1]: "${@:2}" 85*b30d1939SAndy Fiddaman (( Errors < 127 && Errors++ )) 86*b30d1939SAndy Fiddaman} 87*b30d1939SAndy Fiddamanalias err_exit='err_exit $LINENO' 88*b30d1939SAndy Fiddaman 89*b30d1939SAndy Fiddamanset -o nounset 90*b30d1939SAndy FiddamanCommand=${0##*/} 91*b30d1939SAndy Fiddamaninteger Errors=0 92*b30d1939SAndy Fiddaman 93*b30d1939SAndy Fiddaman# common functions/variables 94*b30d1939SAndy Fiddamanfunction isvalidpid 95*b30d1939SAndy Fiddaman{ 96*b30d1939SAndy Fiddaman kill -0 ${1} 2>/dev/null && return 0 97*b30d1939SAndy Fiddaman return 1 98*b30d1939SAndy Fiddaman} 99*b30d1939SAndy Fiddamaninteger testfilesize i maxwait 100*b30d1939SAndy Fiddamantypeset tmpfile 101*b30d1939SAndy Fiddamaninteger testid 102*b30d1939SAndy Fiddaman 103*b30d1939SAndy Fiddaman 104*b30d1939SAndy Fiddaman# test 1: run loop and check various temp filesizes 105*b30d1939SAndy Fiddamantmpfile="$(mktemp -t "sun_solaris_cr_6800929_large_command_substitution_hang.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file." 106*b30d1939SAndy Fiddaman 107*b30d1939SAndy Fiddamancompound -a testcases=( 108*b30d1939SAndy Fiddaman # test 1a: Run test child for $(...) 109*b30d1939SAndy Fiddaman # (note the pipe chain has to end in a builtin command, an external command may not trigger the bug) 110*b30d1939SAndy Fiddaman ( name="test1a" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" ) 111*b30d1939SAndy Fiddaman # test 1b: Same as test1a but uses ${... ; } instead if $(...) 112*b30d1939SAndy Fiddaman ( name="test1b" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" ) 113*b30d1939SAndy Fiddaman # test 1c: Same as test1a but does not use a pipe 114*b30d1939SAndy Fiddaman ( name="test1c" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" ) 115*b30d1939SAndy Fiddaman # test 1d: Same as test1a but does not use a pipe 116*b30d1939SAndy Fiddaman ( name="test1d" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" ) 117*b30d1939SAndy Fiddaman 118*b30d1939SAndy Fiddaman # test 1e: Same as test1a but uses an external "cat" command 119*b30d1939SAndy Fiddaman ( name="test1e" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" ) 120*b30d1939SAndy Fiddaman # test 1f: Same as test1a but uses an external "cat" command 121*b30d1939SAndy Fiddaman ( name="test1f" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" ) 122*b30d1939SAndy Fiddaman # test 1g: Same as test1a but uses an external "cat" command 123*b30d1939SAndy Fiddaman ( name="test1g" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" ) 124*b30d1939SAndy Fiddaman # test 1h: Same as test1a but uses an external "cat" command 125*b30d1939SAndy Fiddaman ( name="test1h" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" ) 126*b30d1939SAndy Fiddaman) 127*b30d1939SAndy Fiddaman 128*b30d1939SAndy Fiddamanfor (( testfilesize=1*1024 ; testfilesize <= 1024*1024 ; testfilesize*=2 )) ; do 129*b30d1939SAndy Fiddaman # Create temp file 130*b30d1939SAndy Fiddaman { 131*b30d1939SAndy Fiddaman for (( i=0 ; i < testfilesize ; i+=64 )) ; do 132*b30d1939SAndy Fiddaman print "0123456789abcdef01234567890ABCDEF0123456789abcdef01234567890ABCDE" 133*b30d1939SAndy Fiddaman done 134*b30d1939SAndy Fiddaman } >"${tmpfile}" 135*b30d1939SAndy Fiddaman 136*b30d1939SAndy Fiddaman # wait up to log2(i) seconds for the child to terminate 137*b30d1939SAndy Fiddaman # (this is 10 seconds for 1KB and 19 seconds for 512KB) 138*b30d1939SAndy Fiddaman (( maxwait=log2(testfilesize) )) 139*b30d1939SAndy Fiddaman 140*b30d1939SAndy Fiddaman for testid in "${!testcases[@]}" ; do 141*b30d1939SAndy Fiddaman nameref currtst=testcases[testid] 142*b30d1939SAndy Fiddaman ${SHELL} -o errexit -c "${currtst.cmd}" >"${tmpfile}.out" & 143*b30d1939SAndy Fiddaman (( childpid=$! )) 144*b30d1939SAndy Fiddaman 145*b30d1939SAndy Fiddaman for (( i=0 ; i < maxwait ; i++ )) ; do 146*b30d1939SAndy Fiddaman isvalidpid ${childpid} || break 147*b30d1939SAndy Fiddaman sleep 0.25 148*b30d1939SAndy Fiddaman done 149*b30d1939SAndy Fiddaman 150*b30d1939SAndy Fiddaman if isvalidpid ${childpid} ; then 151*b30d1939SAndy Fiddaman err_exit "${currtst.name}: child (pid=${childpid}) still busy, filesize=${testfilesize}." 152*b30d1939SAndy Fiddaman kill -KILL ${childpid} 2>/dev/null 153*b30d1939SAndy Fiddaman fi 154*b30d1939SAndy Fiddaman wait || err_exit "${currtst.name}: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 155*b30d1939SAndy Fiddaman 156*b30d1939SAndy Fiddaman # compare input/output 157*b30d1939SAndy Fiddaman cmp -s "${tmpfile}" "${tmpfile}.out" || err_exit "${currtst.name}: ${tmpfile} and ${tmpfile}.out differ, filesize=${testfilesize}." 158*b30d1939SAndy Fiddaman rm "${tmpfile}.out" 159*b30d1939SAndy Fiddaman done 160*b30d1939SAndy Fiddaman 161*b30d1939SAndy Fiddaman # Cleanup 162*b30d1939SAndy Fiddaman rm "${tmpfile}" 163*b30d1939SAndy Fiddamandone 164*b30d1939SAndy Fiddaman 165*b30d1939SAndy Fiddaman 166*b30d1939SAndy Fiddaman# test 2a: Edward Pilatowicz <edward.pilatowicz@sun.com>'s Solaris-specific testcase 167*b30d1939SAndy Fiddaman${SHELL} -o errexit -c 'builtin uniq ; set -- `cat /etc/termcap | sort | uniq` ; true' >/dev/null & 168*b30d1939SAndy Fiddaman(( childpid=$! )) 169*b30d1939SAndy Fiddamansleep 5 170*b30d1939SAndy Fiddamanif isvalidpid ${childpid} ; then 171*b30d1939SAndy Fiddaman err_exit "test2a: child (pid=${childpid}) still busy." 172*b30d1939SAndy Fiddaman kill -KILL ${childpid} 2>/dev/null 173*b30d1939SAndy Fiddamanfi 174*b30d1939SAndy Fiddamanwait || err_exit "test2a: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 175*b30d1939SAndy Fiddaman 176*b30d1939SAndy Fiddaman 177*b30d1939SAndy Fiddaman# test 2b: Same as test 2a but uses ${... ; } instead of $(...) 178*b30d1939SAndy Fiddaman${SHELL} -o errexit -c 'builtin uniq ; set -- ${ cat /etc/termcap | sort | uniq ; } ; true' >/dev/null & 179*b30d1939SAndy Fiddaman(( childpid=$! )) 180*b30d1939SAndy Fiddamansleep 5 181*b30d1939SAndy Fiddamanif isvalidpid ${childpid} ; then 182*b30d1939SAndy Fiddaman err_exit "test2b: child (pid=${childpid}) still busy." 183*b30d1939SAndy Fiddaman kill -KILL ${childpid} 2>/dev/null 184*b30d1939SAndy Fiddamanfi 185*b30d1939SAndy Fiddamanwait || err_exit "test2b: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 186*b30d1939SAndy Fiddaman 187*b30d1939SAndy Fiddaman 188*b30d1939SAndy Fiddaman# test 2c: Same as test 2a but makes sure that "uniq" is not a builtin 189*b30d1939SAndy Fiddaman${SHELL} -o errexit -c 'builtin -d uniq /bin/uniq ; set -- `cat /etc/termcap | sort | uniq` ; true' >/dev/null & 190*b30d1939SAndy Fiddaman(( childpid=$! )) 191*b30d1939SAndy Fiddamansleep 5 192*b30d1939SAndy Fiddamanif isvalidpid ${childpid} ; then 193*b30d1939SAndy Fiddaman err_exit "test2c: child (pid=${childpid}) still busy." 194*b30d1939SAndy Fiddaman kill -KILL ${childpid} 2>/dev/null 195*b30d1939SAndy Fiddamanfi 196*b30d1939SAndy Fiddamanwait || err_exit "test2c: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 197*b30d1939SAndy Fiddaman 198*b30d1939SAndy Fiddaman 199*b30d1939SAndy Fiddaman# test 2d: Same as test 2c but uses ${... ; } instead of $(...) 200*b30d1939SAndy Fiddaman${SHELL} -o errexit -c 'builtin -d uniq /bin/uniq ; set -- ${ cat /etc/termcap | sort | uniq ; } ; true' >/dev/null & 201*b30d1939SAndy Fiddaman(( childpid=$! )) 202*b30d1939SAndy Fiddamansleep 5 203*b30d1939SAndy Fiddamanif isvalidpid ${childpid} ; then 204*b30d1939SAndy Fiddaman err_exit "test2d: child (pid=${childpid}) still busy." 205*b30d1939SAndy Fiddaman kill -KILL ${childpid} 2>/dev/null 206*b30d1939SAndy Fiddamanfi 207*b30d1939SAndy Fiddamanwait || err_exit "test2d: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime) 208*b30d1939SAndy Fiddaman 209*b30d1939SAndy Fiddaman 210*b30d1939SAndy Fiddaman# tests done 211*b30d1939SAndy Fiddamanexit $((Errors)) 212