3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# CDDL HEADER START
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# The contents of this file are subject to the terms of the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# Common Development and Distribution License (the "License").
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# You may not use this file except in compliance with the License.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# or http://www.opensolaris.org/os/licensing.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# See the License for the specific language governing permissions
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# and limitations under the License.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# When distributing Covered Code, include this CDDL HEADER in each
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# If applicable, add the following below this CDDL HEADER, with the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# fields enclosed by brackets "[]" replaced with your own identifying
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# information: Portions Copyright [yyyy] [name of copyright owner]
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# CDDL HEADER END
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# This test checks whether the EXIT trap is called correctly in subshells
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# This was reported as CR #6907460 ("EXIT trap handlers are sometimes executed twice"):
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# ------------ snip ------------
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# During SST testing of snv_128(RE) we found out that ksh93 executes EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# trap handlers twice under some circumstances.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# Here is a test script:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# ---
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# #!/bin/ksh93 -x
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# function A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# set -x
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# trap "print TRAP A >>log" EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# print >&2
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# function B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# set -x
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# trap "print TRAP B >>log" EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# rm -f log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# x=$(B)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# ---
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# It produces the following output on snv_128:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# ---
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + rm -f log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + trap 'print TRAP B >>log' EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + trap 'print TRAP A >>log' EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + print
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + + print TRAP A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# 1>& 2
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + 1>> log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + print TRAP B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + 1>> log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + print TRAP A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + 1>> log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + print TRAP B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + 1>> log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# + x=''
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# ---
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# The log file then contains:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# However, the expected log would be:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# When the "x=$(B)" line is changed to "B", the log is correct:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# TRAP B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# ------------ snip ------------
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# test setup
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerfunction err_exit
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner{
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner print -u2 -n "\t"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner print -u2 -r ${Command}[$1]: "${@:2}"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner (( Errors < 127 && Errors++ ))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner}
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkneralias err_exit='err_exit $LINENO'
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerset -o nounset
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. FaulknerCommand=${0##*/}
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerinteger Errors=0
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknertypeset ocwd
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknertypeset tmpdir
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknertypeset out
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# create temporary test directory
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerocwd="$PWD"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknertmpdir="$(mktemp -t -d "test_sun_solaris_cr_6907460_EXIT_trap_handlers_are_sometimes_executed_twice.XXXXXXXX")" || err_exit "Cannot create temporary directory"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknercd "${tmpdir}" || { err_exit "cd ${tmpdir} failed." ; exit $((Errors)) ; }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# run tests
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# test 1: Run test with some variations
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknercompound vari
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknertypeset testname
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerfor vari.shell_options in \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "-o xtrace" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "-o errexit" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "-o errexit -o xtrace" ; do
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner for vari.xtrace1 in \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "set -x" ; do
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner for vari.xtrace2 in \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "set -x" ; do
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner for vari.func_A_end in \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "print >&2" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "return 0" \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner "print >&2 ; return 0" ; do
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner for vari.subshell in \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'x=$(B)' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'x=$( ( B ) )' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'x=${ B ; }' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'x=${ ( B ) ; }' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'( x=$(B) )' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'( x=$( ( B ) ) )' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'( x=${ B ; } )' \
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner $'( x=${ ( B ) ; } )' ; do
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner testname="$( printf "test |%#B|\n" vari )"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknercat >"testscript.sh" <<EOF
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner function A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ${vari.xtrace1}
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner trap "print TRAP A >>log" EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ${vari.func_A_end}
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner function B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ${vari.xtrace2}
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner trap "print TRAP B >>log" EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner rm -f log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ${vari.subshell}
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. FaulknerEOF
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ${SHELL} ${vari.shell_options} "testscript.sh" >/dev/null 2>&1 || err_exit "${testname}: Unexpected error code $?"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner rm "testscript.sh"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if [[ -f "log" ]] ; then
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner out="$( < log )"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner rm "log"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner else
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner err_exit "${testname}: File 'log' not found."
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner fi
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner [[ "${out}" == $'TRAP A\nTRAP B' ]] || err_exit "${testname}: Expected \$'TRAP A\nTRAP B', got $(printf "%q\n" "${out}")"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner done
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner done
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner done
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner done
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerdone
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# test 2: This is the unmodified test from the bugster bug report
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner(
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknercat <<EOF
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner function A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner set -x
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner trap "print TRAP A >>log" EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner print >&2
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner function B
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner set -x
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner trap "print TRAP B >>log" EXIT
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner A
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner rm -f log
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner x=\$(B)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. FaulknerEOF
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner) | ${SHELL} >/dev/null 2>&1 || err_exit "Unexpected error code $?"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerif [[ -f "log" ]] ; then
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner out="$( < log )"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner rm "log"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerelse
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner err_exit "File 'log' not found."
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerfi
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner[[ "${out}" == $'TRAP A\nTRAP B' ]] || err_exit "Expected \$'TRAP A\nTRAP B', got $(printf "%q\n" "${out}")"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknercd "${ocwd}"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerrmdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# tests done
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerexit $((Errors))