1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2012 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                 Eclipse Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#          http://www.eclipse.org/org/documents/epl-v10.html           #
11#         (with md5 checksum b35adb5213ca9657e911e9befb180842)         #
12#                                                                      #
13#              Information and Software Systems Research               #
14#                            AT&T Research                             #
15#                           Florham Park NJ                            #
16#                                                                      #
17#                  David Korn <dgk@research.att.com>                   #
18#                                                                      #
19########################################################################
20function err_exit
21{
22	print -u2 -n "\t"
23	print -u2 -r ${Command}[$1]: "${@:2}"
24	(( Errors+=1 ))
25}
26
27alias err_exit='err_exit $LINENO'
28
29float DELAY=${1:-0.2}
30integer FOREGROUND=10 BACKGROUND=2 Errors=0
31
32s=$($SHELL -c '
33integer i foreground=0 background=0
34float delay='$DELAY' d=0 s=0
35
36set --errexit
37
38trap "(( background++ ))" CHLD
39
40(( d = delay ))
41for ((i = 0; i < '$BACKGROUND'; i++))
42do	sleep $d &
43	(( d *= 4 ))
44	(( s += d ))
45done
46for ((i = 0; i < '$FOREGROUND'; i++))
47do	(( foreground++ ))
48	sleep $delay
49	(( s -= delay ))
50	$SHELL -c : > /dev/null # foreground does not generate SIGCHLD
51done
52if	(( (s += delay) < 1 ))
53then	(( s = 1 ))
54fi
55sleep $s
56wait
57print foreground=$foreground background=$background
58') || err_exit "test loop failed"
59
60eval $s
61
62(( foreground == FOREGROUND )) || err_exit "expected '$FOREGROUND foreground' -- got '$foreground' (DELAY=$DELAY)"
63(( background == BACKGROUND )) || err_exit "expected '$BACKGROUND background' -- got '$background' (DELAY=$DELAY)"
64
65set --noerrexit
66
67if	[[ ${.sh.version} == Version?*([[:upper:]])J* ]]
68then
69
70	jobmax=4
71	got=$($SHELL -c '
72		JOBMAX='$jobmax' JOBCOUNT=$(('$jobmax'*2))
73		integer running=0 maxrunning=0
74		trap "((running--))" CHLD
75		for ((i=0; i<JOBCOUNT; i++))
76		do	sleep 1 &
77			if	((++running > maxrunning))
78			then	((maxrunning=running))
79			fi
80		done
81		wait
82		print running=$running maxrunning=$maxrunning
83	')
84	exp='running=0 maxrunning='$jobmax
85	[[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected '$exp', got '$got'"
86
87	got=$($SHELL -c '
88		typeset -A proc
89
90		trap "
91			print \${proc[\$!].name} \${proc[\$!].status} \$?
92			unset proc[\$!]
93		" CHLD
94
95		{ sleep 3; print a; exit 1; } &
96		proc[$!]=( name=a status=1 )
97
98		{ sleep 2; print b; exit 2; } &
99		proc[$!]=( name=b status=2 )
100
101		{ sleep 1; print c; exit 3; } &
102		proc[$!]=( name=c status=3 )
103
104		while	(( ${#proc[@]} ))
105		do	sleep -s
106		done
107	')
108	exp='c\nc 3 3\nb\nb 2 2\na\na 1 1'
109	[[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected $(printf %q "$exp"), got $(printf %q "$got")"
110
111fi
112
113{
114got=$( ( sleep 1;print $'\n') | $SHELL -c 'function handler { : ;}
115	trap handler CHLD; sleep .3 & IFS= read; print good')
116} 2> /dev/null
117[[ $got == good ]] || err_exit 'SIGCLD handler effects read behavior'
118
119set -- $(
120	(
121	$SHELL -xc $'
122		trap \'wait $!; print $! $?\' CHLD
123		{ sleep 0.1; exit 9; } &
124		print $!
125		sleep 0.5
126	'
127	) 2>/dev/null; print $?
128)
129if	(( $# != 4 ))
130then	err_exit "CHLD trap failed -- expected 4 args, got $#"
131elif	(( $4 != 0 ))
132then	err_exit "CHLD trap failed -- exit code $4"
133elif	(( $1 != $2 ))
134then	err_exit "child pid mismatch -- got '$1' != '$2'"
135elif	(( $3 != 9 ))
136then	err_exit "child status mismatch -- expected '9', got '$3'"
137fi
138
139trap '' CHLD
140integer d
141for ((d=0; d < 2000; d++))
142do      if      print foo | grep bar
143        then    break
144        fi
145done
146(( d==2000 )) ||  err_exit "trap '' CHLD  causes side effects d=$d"
147trap - CHLD
148
149tmp=$(mktemp -dt)
150trap 'rm -rf $tmp' EXIT
151x=$($SHELL 2> /dev/null -ic '/bin/notfound; sleep .5 & sleep 1;jobs')
152[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after notfound'
153x=$($SHELL 2> /dev/null  -ic 'kill -0 12345678901234567876; sleep .5 & sleep 1;jobs')
154[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after error message'
155print 'set -o monitor;sleep .5 & sleep 1;jobs' > $tmp/foobar
156chmod +x $tmp/foobar
157x=$($SHELL  -c "echo | $tmp/foobar")
158[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked for script at end of pipeline'
159
160exit $((Errors<125?Errors:125))
161