xref: /titanic_51/usr/src/lib/libshell/common/tests/signal.sh (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
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