17c2fbfb3SApril Chin######################################################################## 27c2fbfb3SApril Chin# # 37c2fbfb3SApril Chin# This software is part of the ast package # 4*3e14f97fSRoger A. Faulkner# Copyright (c) 1982-2010 AT&T Intellectual Property # 57c2fbfb3SApril Chin# and is licensed under the # 67c2fbfb3SApril Chin# Common Public License, Version 1.0 # 77c2fbfb3SApril Chin# by AT&T Intellectual Property # 87c2fbfb3SApril Chin# # 97c2fbfb3SApril Chin# A copy of the License is available at # 107c2fbfb3SApril Chin# http://www.opensource.org/licenses/cpl1.0.txt # 117c2fbfb3SApril Chin# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 127c2fbfb3SApril Chin# # 137c2fbfb3SApril Chin# Information and Software Systems Research # 147c2fbfb3SApril Chin# AT&T Research # 157c2fbfb3SApril Chin# Florham Park NJ # 167c2fbfb3SApril Chin# # 177c2fbfb3SApril Chin# David Korn <dgk@research.att.com> # 187c2fbfb3SApril Chin# # 197c2fbfb3SApril Chin######################################################################## 207c2fbfb3SApril Chinfunction err_exit 217c2fbfb3SApril Chin{ 227c2fbfb3SApril Chin print -u2 -n "\t" 237c2fbfb3SApril Chin print -u2 -r ${Command}[$1]: "${@:2}" 247c2fbfb3SApril Chin (( Errors++ )) 257c2fbfb3SApril Chin} 267c2fbfb3SApril Chinalias err_exit='err_exit $LINENO' 277c2fbfb3SApril Chin 287c2fbfb3SApril ChinCommand=${0##*/} 297c2fbfb3SApril Chininteger Errors=0 307c2fbfb3SApril Chin 3134f9b3eeSRoland Mainztmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 3234f9b3eeSRoland Mainztrap "cd /; rm -rf $tmp" EXIT 3334f9b3eeSRoland Mainz 3434f9b3eeSRoland Mainzcd $tmp || err_exit "cd $tmp failed" 3534f9b3eeSRoland Mainz 3634f9b3eeSRoland Mainz( 3734f9b3eeSRoland Mainz set --pipefail 3834f9b3eeSRoland Mainz { 3934f9b3eeSRoland Mainz $SHELL 2> out2 <<- \EOF 4034f9b3eeSRoland Mainz g=false 4134f9b3eeSRoland Mainz trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE 4234f9b3eeSRoland Mainz while : 4334f9b3eeSRoland Mainz do print hello 4434f9b3eeSRoland Mainz done 4534f9b3eeSRoland Mainz EOF 4634f9b3eeSRoland Mainz } | head > /dev/null 4734f9b3eeSRoland Mainz (( $? == 0)) || err_exit "SIGPIPE with wrong error code $?" 4834f9b3eeSRoland Mainz [[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct' 4934f9b3eeSRoland Mainz) & 5034f9b3eeSRoland Mainzcop=$! 5134f9b3eeSRoland Mainz{ sleep 4; kill $cop; } 2>/dev/null & 5234f9b3eeSRoland Mainzspy=$! 5334f9b3eeSRoland Mainzif wait $cop 2>/dev/null 5434f9b3eeSRoland Mainzthen kill $spy 2>/dev/null 5534f9b3eeSRoland Mainzelse err_exit "pipe with --pipefail PIPE trap hangs" 5634f9b3eeSRoland Mainzfi 5734f9b3eeSRoland Mainzwait 5834f9b3eeSRoland Mainzrm -f out2 597c2fbfb3SApril Chin 607c2fbfb3SApril Chin[[ $( trap 'print -n got_child' SIGCHLD 617c2fbfb3SApril Chin sleep 2 & 627c2fbfb3SApril Chin for ((i=0; i < 4; i++)) 6334f9b3eeSRoland Mainz do sleep .75 647c2fbfb3SApril Chin print -n $i 657c2fbfb3SApril Chin done) == 01got_child23 ]] || err_exit 'SIGCHLD not working' 667c2fbfb3SApril Chin 677c2fbfb3SApril Chin# begin standalone SIGINT test generation 687c2fbfb3SApril Chin 697c2fbfb3SApril Chincat > tst <<'!' 707c2fbfb3SApril Chin# shell trap tests 717c2fbfb3SApril Chin# 727c2fbfb3SApril Chin# tst control script that calls tst-1, must be run by ksh 737c2fbfb3SApril Chin# tst-1 calls tst-2 747c2fbfb3SApril Chin# tst-2 calls tst-3 757c2fbfb3SApril Chin# tst-3 defaults or handles and discards/propagates SIGINT 767c2fbfb3SApril Chin# 777c2fbfb3SApril Chin# initial -v option lists script entry and SIGINT delivery 787c2fbfb3SApril Chin# 797c2fbfb3SApril Chin# three test options 807c2fbfb3SApril Chin# 817c2fbfb3SApril Chin# d call next script directly, otherwise via $SHELL -c 827c2fbfb3SApril Chin# t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x 8334f9b3eeSRoland Mainz# x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default 8434f9b3eeSRoland Mainz# z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default 857c2fbfb3SApril Chin# 867c2fbfb3SApril Chin# Usage: tst [-v] [-options] shell-to-test ... 877c2fbfb3SApril Chin 887c2fbfb3SApril Chin# "trap + sig" is an unadvertized extension for this test 897c2fbfb3SApril Chin# if run from nmake SIGINT is set to SIG_IGN 907c2fbfb3SApril Chin# this call sets it back to SIG_DFL 917c2fbfb3SApril Chin# semantics w.r.t. function scope must be worked out before 927c2fbfb3SApril Chin# making it public 937c2fbfb3SApril Chintrap + INT 947c2fbfb3SApril Chin 957c2fbfb3SApril Chinset -o monitor 967c2fbfb3SApril Chin 977c2fbfb3SApril Chinfunction gen 987c2fbfb3SApril Chin{ 997c2fbfb3SApril Chin typeset o t x d 10034f9b3eeSRoland Mainz for x in - x z 1017c2fbfb3SApril Chin do case $x in 1027c2fbfb3SApril Chin [$1]) for t in - t 1037c2fbfb3SApril Chin do case $t in 1047c2fbfb3SApril Chin [$1]) for d in - d 1057c2fbfb3SApril Chin do case $d in 1067c2fbfb3SApril Chin [$1]) o="$o $x$t$d" 1077c2fbfb3SApril Chin esac 1087c2fbfb3SApril Chin done 1097c2fbfb3SApril Chin esac 1107c2fbfb3SApril Chin done 1117c2fbfb3SApril Chin esac 1127c2fbfb3SApril Chin done 1137c2fbfb3SApril Chin echo '' $o 1147c2fbfb3SApril Chin} 1157c2fbfb3SApril Chin 1167c2fbfb3SApril Chincase $1 in 1177c2fbfb3SApril Chin-v) v=v; shift ;; 1187c2fbfb3SApril Chin-*v*) v=v ;; 1197c2fbfb3SApril Chin*) v= ;; 1207c2fbfb3SApril Chinesac 1217c2fbfb3SApril Chincase $1 in 1227c2fbfb3SApril Chin*' '*) o=$1; shift ;; 1237c2fbfb3SApril Chin-*) o=$(gen $1); shift ;; 1247c2fbfb3SApril Chin*) o=$(gen -txd) ;; 1257c2fbfb3SApril Chinesac 1267c2fbfb3SApril Chincase $# in 1277c2fbfb3SApril Chin0) set ksh bash ksh88 pdksh ash zsh ;; 1287c2fbfb3SApril Chinesac 1297c2fbfb3SApril Chinfor f in $o 1307c2fbfb3SApril Chindo case $# in 1317c2fbfb3SApril Chin 1) ;; 1327c2fbfb3SApril Chin *) echo ;; 1337c2fbfb3SApril Chin esac 1347c2fbfb3SApril Chin for sh 1357c2fbfb3SApril Chin do if $sh -c 'exit 0' > /dev/null 2>&1 1367c2fbfb3SApril Chin then case $# in 1377c2fbfb3SApril Chin 1) printf '%3s ' "$f" ;; 1387c2fbfb3SApril Chin *) printf '%16s %3s ' "$sh" "$f" ;; 1397c2fbfb3SApril Chin esac 1407c2fbfb3SApril Chin $sh tst-1 $v$f $sh > tst.out & 1417c2fbfb3SApril Chin wait 1427c2fbfb3SApril Chin echo $(cat tst.out) 1437c2fbfb3SApril Chin fi 1447c2fbfb3SApril Chin done 1457c2fbfb3SApril Chindone 1467c2fbfb3SApril Chincase $# in 1477c2fbfb3SApril Chin1) ;; 1487c2fbfb3SApril Chin*) echo ;; 1497c2fbfb3SApril Chinesac 1507c2fbfb3SApril Chin! 1517c2fbfb3SApril Chincat > tst-1 <<'!' 1527c2fbfb3SApril Chinexec 2>/dev/null 1537c2fbfb3SApril Chincase $1 in 1547c2fbfb3SApril Chin*v*) echo 1-main ;; 1557c2fbfb3SApril Chinesac 1567c2fbfb3SApril Chin{ 1577c2fbfb3SApril Chin sleep 2 1587c2fbfb3SApril Chin case $1 in 1597c2fbfb3SApril Chin *v*) echo "SIGINT" ;; 1607c2fbfb3SApril Chin esac 1617c2fbfb3SApril Chin kill -s INT 0 1627c2fbfb3SApril Chin} & 1637c2fbfb3SApril Chincase $1 in 1647c2fbfb3SApril Chin*t*) trap ' 1657c2fbfb3SApril Chin echo 1-intr 1667c2fbfb3SApril Chin trap - INT 1677c2fbfb3SApril Chin # omitting the self kill exposes shells that deliver 1687c2fbfb3SApril Chin # the SIGINT trap but exit 0 for -xt 1697c2fbfb3SApril Chin # kill -s INT $$ 1707c2fbfb3SApril Chin ' INT 1717c2fbfb3SApril Chin ;; 1727c2fbfb3SApril Chinesac 1737c2fbfb3SApril Chincase $1 in 1747c2fbfb3SApril Chin*d*) tst-2 $1 $2; status=$? ;; 1757c2fbfb3SApril Chin*) $2 -c "tst-2 $1 $2"; status=$? ;; 1767c2fbfb3SApril Chinesac 1777c2fbfb3SApril Chinprintf '1-%04d\n' $status 1787c2fbfb3SApril Chinsleep 2 1797c2fbfb3SApril Chin! 1807c2fbfb3SApril Chincat > tst-2 <<'!' 1817c2fbfb3SApril Chincase $1 in 18234f9b3eeSRoland Mainz*z*) trap ' 18334f9b3eeSRoland Mainz echo 2-intr 18434f9b3eeSRoland Mainz exit 0 18534f9b3eeSRoland Mainz ' INT 18634f9b3eeSRoland Mainz ;; 1877c2fbfb3SApril Chin*x*) trap ' 1887c2fbfb3SApril Chin echo 2-intr 1897c2fbfb3SApril Chin exit 1907c2fbfb3SApril Chin ' INT 1917c2fbfb3SApril Chin ;; 1927c2fbfb3SApril Chin*t*) trap ' 1937c2fbfb3SApril Chin echo 2-intr 1947c2fbfb3SApril Chin trap - INT 1957c2fbfb3SApril Chin kill -s INT $$ 1967c2fbfb3SApril Chin ' INT 1977c2fbfb3SApril Chin ;; 1987c2fbfb3SApril Chinesac 1997c2fbfb3SApril Chincase $1 in 2007c2fbfb3SApril Chin*v*) echo 2-main ;; 2017c2fbfb3SApril Chinesac 2027c2fbfb3SApril Chincase $1 in 2037c2fbfb3SApril Chin*d*) tst-3 $1 $2; status=$? ;; 2047c2fbfb3SApril Chin*) $2 -c "tst-3 $1 $2"; status=$? ;; 2057c2fbfb3SApril Chinesac 2067c2fbfb3SApril Chinprintf '2-%04d\n' $status 2077c2fbfb3SApril Chin! 2087c2fbfb3SApril Chincat > tst-3 <<'!' 2097c2fbfb3SApril Chincase $1 in 21034f9b3eeSRoland Mainz*[xz]*) trap ' 2117c2fbfb3SApril Chin sleep 2 2127c2fbfb3SApril Chin echo 3-intr 2137c2fbfb3SApril Chin exit 0 2147c2fbfb3SApril Chin ' INT 2157c2fbfb3SApril Chin ;; 2167c2fbfb3SApril Chin*) trap ' 2177c2fbfb3SApril Chin sleep 2 2187c2fbfb3SApril Chin echo 3-intr 2197c2fbfb3SApril Chin trap - INT 2207c2fbfb3SApril Chin kill -s INT $$ 2217c2fbfb3SApril Chin ' INT 2227c2fbfb3SApril Chin ;; 2237c2fbfb3SApril Chinesac 2247c2fbfb3SApril Chincase $1 in 2257c2fbfb3SApril Chin*v*) echo 3-main ;; 2267c2fbfb3SApril Chinesac 2277c2fbfb3SApril Chinsleep 5 2287c2fbfb3SApril Chinprintf '3-%04d\n' $? 2297c2fbfb3SApril Chin! 2307c2fbfb3SApril Chinchmod +x tst tst-? 2317c2fbfb3SApril Chin 2327c2fbfb3SApril Chin# end standalone test generation 2337c2fbfb3SApril Chin 2347c2fbfb3SApril Chinexport PATH=$PATH: 2357c2fbfb3SApril Chintypeset -A expected 2367c2fbfb3SApril Chinexpected[---]="3-intr" 2377c2fbfb3SApril Chinexpected[--d]="3-intr" 2387c2fbfb3SApril Chinexpected[-t-]="3-intr 2-intr 1-intr 1-0258" 2397c2fbfb3SApril Chinexpected[-td]="3-intr 2-intr 1-intr 1-0258" 24034f9b3eeSRoland Mainzexpected[x--]="3-intr 2-intr" 24134f9b3eeSRoland Mainzexpected[x-d]="3-intr 2-intr" 24234f9b3eeSRoland Mainzexpected[xt-]="3-intr 2-intr 1-intr 1-0258" 24334f9b3eeSRoland Mainzexpected[xtd]="3-intr 2-intr 1-intr 1-0258" 24434f9b3eeSRoland Mainzexpected[z--]="3-intr 2-intr 1-0000" 24534f9b3eeSRoland Mainzexpected[z-d]="3-intr 2-intr 1-0000" 24634f9b3eeSRoland Mainzexpected[zt-]="3-intr 2-intr 1-intr 1-0000" 24734f9b3eeSRoland Mainzexpected[ztd]="3-intr 2-intr 1-intr 1-0000" 2487c2fbfb3SApril Chin 2497c2fbfb3SApril Chintst $SHELL > tst.got 2507c2fbfb3SApril Chin 2517c2fbfb3SApril Chinwhile read ops out 2527c2fbfb3SApril Chindo [[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'" 2537c2fbfb3SApril Chindone < tst.got 2547c2fbfb3SApril Chin 2557c2fbfb3SApril Chinfloat s=$SECONDS 2567c2fbfb3SApril Chin[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent' 2577c2fbfb3SApril Chin(( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal' 2587c2fbfb3SApril Chin((s = SECONDS)) 2597c2fbfb3SApril Chin[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent' 2607c2fbfb3SApril Chin(( SECONDS-s < 4 )) && err_exit 'parent completes early' 26134f9b3eeSRoland Mainz 26234f9b3eeSRoland Mainzunset n s t 26334f9b3eeSRoland Mainzfor s in $(kill -l) 26434f9b3eeSRoland Mainzdo if ! n=$(kill -l $s 2>/dev/null) 26534f9b3eeSRoland Mainz then err_exit "'kill -l $s' failed" 26634f9b3eeSRoland Mainz continue 26734f9b3eeSRoland Mainz fi 26834f9b3eeSRoland Mainz if ! t=$(kill -l $n 2>/dev/null) 26934f9b3eeSRoland Mainz then err_exit "'kill -l $n' failed" 27034f9b3eeSRoland Mainz continue 27134f9b3eeSRoland Mainz fi 27234f9b3eeSRoland Mainz if [[ $s == ?(SIG)$t ]] 27334f9b3eeSRoland Mainz then continue 27434f9b3eeSRoland Mainz fi 27534f9b3eeSRoland Mainz if ! m=$(kill -l $t 2>/dev/null) 27634f9b3eeSRoland Mainz then err_exit "'kill -l $t' failed" 27734f9b3eeSRoland Mainz continue 27834f9b3eeSRoland Mainz fi 27934f9b3eeSRoland Mainz if [[ $m == $n ]] 28034f9b3eeSRoland Mainz then continue 28134f9b3eeSRoland Mainz fi 28234f9b3eeSRoland Mainz err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n" 28334f9b3eeSRoland Mainzdone 28434f9b3eeSRoland Mainzyes=$(whence -p yes) 28534f9b3eeSRoland Mainz[[ $yes ]] && for exp in TERM VTALRM PIPE 28634f9b3eeSRoland Mainzdo { $SHELL <<- EOF 28734f9b3eeSRoland Mainz foo() { return 0; } 28834f9b3eeSRoland Mainz trap foo EXIT 28934f9b3eeSRoland Mainz { sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } & 29034f9b3eeSRoland Mainz $yes | while read yes; do 29134f9b3eeSRoland Mainz (/bin/date; sleep .1) 29234f9b3eeSRoland Mainz done > /dev/null 29334f9b3eeSRoland Mainz EOF 29434f9b3eeSRoland Mainz } 2>> /dev/null 29534f9b3eeSRoland Mainz got=$(kill -l $?) 29634f9b3eeSRoland Mainz [[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'" 29734f9b3eeSRoland Mainzdone 29834f9b3eeSRoland Mainz 29934f9b3eeSRoland MainzSECONDS=0 30034f9b3eeSRoland Mainz$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit 3" EXIT; (sleep 5);print finished' > $tmp/sig 30134f9b3eeSRoland Mainz(( $?==3)) || err_exit "wrong exit status expecting 3 got $?" 30234f9b3eeSRoland Mainzx=$(<$tmp/sig) 30334f9b3eeSRoland Mainz[[ $x == done ]] || err_exit "wrong result - execting done got $x" 30434f9b3eeSRoland Mainz(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expecting around 2" 30534f9b3eeSRoland Mainz 30634f9b3eeSRoland MainzSECONDS=0 30734f9b3eeSRoland Mainz{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit" EXIT; (sleep 5);print finished' > $tmp/sig ;} 2> /dev/null 30834f9b3eeSRoland Mainz[[ $(kill -l $?) == TERM ]] || err_exit "wrong exit status expecting TERM got $(kill -l $?)" 30934f9b3eeSRoland Mainzx=$(<$tmp/sig) 31034f9b3eeSRoland Mainz[[ $x == done ]] || err_exit "wrong result - execting done got $x" 31134f9b3eeSRoland Mainz(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expecting around 2" 31234f9b3eeSRoland Mainz 31334f9b3eeSRoland MainzSECONDS=0 31434f9b3eeSRoland Mainzx=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit 3" EXIT; (sleep 5);print finished') 31534f9b3eeSRoland Mainz(( $?==3)) || err_exit "wrong exit status expecting 3 got $?" 31634f9b3eeSRoland Mainz[[ $x == done ]] || err_exit "wrong result - execting done got $x" 31734f9b3eeSRoland Mainz(( SECONDS < 4 )) && err_exit "took $SECONDS seconds, expecting around 5" 31834f9b3eeSRoland Mainz 31934f9b3eeSRoland Mainztrap '' SIGBUS 32034f9b3eeSRoland Mainz[[ $($SHELL -c 'trap date SIGBUS;trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap' 32134f9b3eeSRoland Mainztrap -- - SIGBUS 32234f9b3eeSRoland Mainz 3237c2fbfb3SApril Chinexit $((Errors)) 324