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) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24 #
  25 
  26 #
  27 # This test checks whether the return code of a child process
  28 # is reported properly.
  29 #
  30 # This was reported as CR #6887363 ("Korn shell 93 sometimes
  31 # mishandles return value of its child process"):
  32 # ------------ snip ------------
  33 # Following construction sometimes ends with wrong return value.
  34 # 
  35 #      56        echo $op | grep rand 2>&1 >/dev/null
  36 #      57        if [ $? = 0 ]; then
  37 #      58               randseq="rand${SEED}"
  38 #      59        else
  39 #      60               randseq="seq"
  40 #      61        fi
  41 # 
  42 # Sometimes, the given result is "rand..." even when there is
  43 # no "rand" word in $op. This can be demonstrated with
  44 # TSufs/SnapShots/Func test case which excercises shown code
  45 # quite often.
  46 # 
  47 # As it happens only sometimes, I suppose there is an
  48 # race-condition in handling return value from a child process.
  49 # ------------ snip ------------
  50 #
  51 
  52 # test setup
  53 function err_exit
  54 {
  55         print -u2 -n "\t"
  56         print -u2 -r ${Command}[$1]: "${@:2}"
  57         (( Errors < 127 && Errors++ ))
  58 }
  59 alias err_exit='err_exit $LINENO'
  60 
  61 set -o nounset
  62 Command=${0##*/}
  63 integer Errors=0
  64 
  65 typeset ocwd
  66 typeset tmpdir
  67 typeset out
  68 
  69 # create temporary test directory
  70 ocwd="$PWD"
  71 tmpdir="$(mktemp -t -d "test_sun_solaris_cr_6887363_shell_sometimes_mishandles_return_value_of_its_child_process.XXXXXXXX")" || err_exit "Cannot create temporary directory"
  72 
  73 cd "${tmpdir}" || { err_exit "cd ${tmpdir} failed." ; exit $((Errors)) ; }
  74 
  75 
  76 # run tests
  77 
  78 # print test case from bug that ksh93 can read this script via stdin
  79 function cat_test
  80 {
  81 cat <<EOF
  82 #!/bin/sh
  83 #
  84 # Test derived from Sun's SnapShots Functional Suite
  85 # 
  86 
  87 export PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
  88 
  89 # WARNING: make sure "expr" and "grep" are _external_ commands in this test
  90 
  91 # start test
  92 _pcnt=0
  93 
  94 PASS(){
  95         _pcnt=\`/usr/bin/expr \$_pcnt + 1\`
  96         true
  97 }
  98 
  99 doblockstamper() {
 100         output=\`/usr/bin/sleep .01\`
 101         _status=\$?
 102 
 103         PASS "Here I am"
 104 }
 105 
 106 lotsaFiles() {
 107         OPS="read-seq read-rand syncread-seq syncread-seq"
 108         echo \$OPS
 109         for op in \$OPS; do
 110          echo \$op
 111          echo \$op | /usr/bin/grep rand 2>&1 >/dev/null
 112          status=\$?
 113          if [ \$status = 0 ]; then
 114                 randseq="rand"
 115                 phrase="read-rand"
 116          else
 117                 randseq="seq"
 118                 phrase="read-seq"
 119          fi
 120          retcode=\$status
 121 
 122          echo \$op | /usr/bin/grep sync 2>&1 >/dev/null
 123          status=\$?
 124          if [ \$status = 0 ]; then
 125                 syncasync="sync"
 126                 phrase="sync\$phrase"
 127          else
 128                 syncasync="async"
 129          fi
 130          retcode=\${status}-\${retcode}
 131 
 132         if [ "\$op" != "\$phrase" ]; then
 133                 echo "Bad mode: \$op != \$phrase (\$retcode)"
 134                 exit 2
 135         fi
 136 
 137          for sz in 1 2 3 4; do
 138            for type in 1 2 3 4; do
 139                 PASS "Something"
 140                 doblockstamper &
 141            done
 142            wait # Let a few finish
 143          done
 144         done
 145 
 146         wait    # Make sure everyone got done
 147 
 148         PASS "lotsafiles \$1 \$fill"
 149 }
 150 
 151 cycle=0
 152 while [ cycle -lt 24 ]; do
 153         cycle=\`/usr/bin/expr \$cycle + 1\`
 154 
 155         lotsaFiles write
 156         lotsaFiles write
 157         lotsaFiles write
 158 
 159         lotsaFiles read
 160         lotsaFiles read
 161         lotsaFiles read
 162 
 163         PASS "Cycle"
 164 done
 165 exit 0
 166 EOF
 167 }
 168 
 169 # FIXME: we reset the VMALLOC_OPTIONS (and the depreciated VMDEBUG (for now)) variable for the run to avoid
 170 # that the test may run for hours. This may require re-investigation why this happens.
 171 out="$(unset VMALLOC_OPTIONS VMDEBUG ; cat_test | ${SHELL} 2>&1)" || err_exit "Unexpected exit code $?"
 172 [[ "${out}" != "" ]] || err_exit "No output from test"
 173 
 174 # filter output and check it
 175 out2="$(/usr/bin/egrep -v '^((read-seq|read-rand|syncread-seq|syncread-seq)[[:space:][:blank:]]*)*$' <<<"${out}")"
 176 [[ "${out2}" == "" ]] || err_exit "Unexpected output '${out2}'"
 177 
 178 
 179 cd "${ocwd}"
 180 rmdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
 181 
 182 # tests done
 183 exit $((Errors))