1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or http://www.opensolaris.org/os/licensing. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21 22# 23# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24# 25 26# 27# This test checks whether the issue described in CR #6687139 28# ("command substitution, exec, and stdout redirection cause 29# allocation loop") has been fixed: 30# -- snip -- 31# The following one-liner (including back ticks) causes ksh93 to spin 32# out of control consuming all memory at a *very* rapid pace: 33# 34# `exec program > file` 35# 36# If "file" is a real file (as opposed to /dev/null), the file will 37# also grow without bound. "program" need not exist, i.e. 38# 39# `exec > file` 40# 41# has the same result. Using $() instead of `` also has the same 42# effect. 43# 44# This works fine under all other bourne-compatible shells. 45# -- snip -- 46# 47 48# test setup 49function err_exit 50{ 51 print -u2 -n "\t" 52 print -u2 -r ${Command}[$1]: "${@:2}" 53 (( Errors < 127 && Errors++ )) 54} 55alias err_exit='err_exit $LINENO' 56 57set -o nounset 58Command=${0##*/} 59integer Errors=0 60 61function isvalidpid 62{ 63 kill -0 ${1} 2>/dev/null && return 0 64 return 1 65} 66 67integer childpid 68typeset testdir 69integer childretval 70 71testdir="/tmp/sun_solaris_cr_6687139_pid$$_${PPID}" 72mkdir -p "${testdir}" || err_exit "Cannot create test dirctory" 73cd "${testdir}" || { err_exit "Cannot cd to test dirctory" ; exit $Errors ; } 74 75############################################################################## 76## 77## test variant 1a: Use command substitution $( ... ) 78## 79 80# Run testcase with "nice" to make sure a "runaway" process can 81# still be caught&&terminated by the current shell 82nice -n 10 ${SHELL} -c 'touch z ; $(exec nosuchprogram_for_cr_6687139 > z) ; rm z' 2>/dev/null & 83childpid=$! 84 85sleep 5 86 87if isvalidpid ${childpid} ; then 88 # First _stop_, then log error since the child may eat up memory 89 # VERY VERY quickly 90 kill -STOP ${childpid} 91 92 err_exit "Child still active after 5 seconds (hang ?)" 93 94 # Get sample stack trace 95 pstack ${childpid} 96 kill -KILL ${childpid} 97fi 98 99# collect child's return status 100wait ${childpid} 101childretval=$? 102 103(( childretval == 0 )) || err_exit "Child returned non-zero exit code ${childretval}." 104 105[[ ! -f "z" ]] || { rm "z" ; err_exit "Child did not remove test file" ; } 106 107 108############################################################################## 109## 110## test variant 1b: Same as test 1a but forces the shell to |fork()| for the 111## subshell 112## 113 114# Run testcase with "nice" to make sure a "runaway" process can 115# still be caught&&terminated by the current shell 116nice -n 10 ${SHELL} -c 'touch z ; $(ulimit -c 0 ; exec nosuchprogram_for_cr_6687139 > z) ; rm z' 2>/dev/null & 117childpid=$! 118 119sleep 5 120 121if isvalidpid ${childpid} ; then 122 # First _stop_, then log error since the child may eat up memory 123 # VERY VERY quickly 124 kill -STOP ${childpid} 125 126 err_exit "Child still active after 5 seconds (hang ?)" 127 128 # Get sample stack trace 129 pstack ${childpid} 130 kill -KILL ${childpid} 131fi 132 133# collect child's return status 134wait ${childpid} 135childretval=$? 136 137(( childretval == 0 )) || err_exit "Child returned non-zero exit code ${childretval}." 138 139[[ ! -f "z" ]] || { rm "z" ; err_exit "Child did not remove test file" ; } 140 141 142############################################################################## 143## 144## test variant 2a: Use plain subshell ( ... ) 145## 146 147# Run testcase with "nice" to make sure a "runaway" process can 148# still be caught&&terminated by the current shell 149nice -n 10 ${SHELL} -c 'touch z ; (exec nosuchprogram_for_cr_6687139 > z) ; rm z' 2>/dev/null & 150childpid=$! 151 152sleep 5 153 154if isvalidpid ${childpid} ; then 155 # First _stop_, then log error since the child may eat up memory 156 # VERY VERY quickly 157 kill -STOP ${childpid} 158 159 err_exit "Child still active after 5 seconds (hang ?)" 160 161 # Get sample stack trace 162 pstack ${childpid} 163 kill -KILL ${childpid} 164fi 165 166# collect child's return status 167wait ${childpid} 168childretval=$? 169 170(( childretval == 0 )) || err_exit "Child returned non-zero exit code ${childretval}." 171 172[[ ! -f "z" ]] || { rm "z" ; err_exit "Child did not remove test file" ; } 173 174 175############################################################################## 176## 177## test variant 2b: Same as test 2a but forces the shell to |fork()| for the 178## subshell 179## 180 181# Run testcase with "nice" to make sure a "runaway" process can 182# still be caught&&terminated by the current shell 183nice -n 10 ${SHELL} -c 'touch z ; (ulimit -c 0 ; exec nosuchprogram_for_cr_6687139 > z) ; rm z' 2>/dev/null & 184childpid=$! 185 186sleep 5 187 188if isvalidpid ${childpid} ; then 189 # First _stop_, then log error since the child may eat up memory 190 # VERY VERY quickly 191 kill -STOP ${childpid} 192 193 err_exit "Child still active after 5 seconds (hang ?)" 194 195 # Get sample stack trace 196 pstack ${childpid} 197 kill -KILL ${childpid} 198fi 199 200# collect child's return status 201wait ${childpid} 202childretval=$? 203 204(( childretval == 0 )) || err_exit "Child returned non-zero exit code ${childretval}." 205 206[[ ! -f "z" ]] || { rm "z" ; err_exit "Child did not remove test file" ; } 207 208# tests done, remove temporary test subdir 209cd /tmp 210rmdir "${testdir}" || err_exit "Could not remove temporary test directory ${testdir}" 211 212 213# tests done 214exit $((Errors)) 215