Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/tests/signal.sh
1810 views
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 <[email protected]> #
18
# #
19
########################################################################
20
function err_exit
21
{
22
print -u2 -n "\t"
23
print -u2 -r ${Command}[$1]: "${@:2}"
24
(( Errors++ ))
25
}
26
alias err_exit='err_exit $LINENO'
27
28
Command=${0##*/}
29
integer Errors=0
30
31
tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32
trap "cd /; rm -rf $tmp" EXIT
33
34
cd $tmp || err_exit "cd $tmp failed"
35
36
unset n s t
37
typeset -A SIG
38
for s in $(kill -l)
39
do if ! n=$(kill -l $s 2>/dev/null)
40
then err_exit "'kill -l $s' failed"
41
elif ! t=$(kill -l $n 2>/dev/null)
42
then err_exit "'kill -l $n' failed"
43
elif [[ $s == ?(SIG)$t ]]
44
then SIG[${s#SIG}]=1
45
elif ! m=$(kill -l $t 2>/dev/null)
46
then err_exit "'kill -l $t' failed"
47
elif [[ $m != $n ]]
48
then err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n"
49
fi
50
done
51
52
(
53
set --pipefail
54
{
55
$SHELL 2> out2 <<- \EOF
56
g=false
57
trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE
58
while :
59
do print hello
60
done
61
EOF
62
} | head > /dev/null
63
(( $? == 0)) || err_exit "SIGPIPE with wrong error code $?"
64
[[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct'
65
) &
66
cop=$!
67
{ sleep 4; kill $cop; } 2>/dev/null &
68
spy=$!
69
if wait $cop 2>/dev/null
70
then kill $spy 2>/dev/null
71
else err_exit "pipe with --pipefail PIPE trap hangs"
72
fi
73
wait
74
rm -f out2
75
76
[[ $( trap 'print -n got_child' SIGCHLD
77
sleep 2 &
78
for ((i=0; i < 4; i++))
79
do sleep .75
80
print -n $i
81
done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
82
83
# begin standalone SIGINT test generation
84
85
cat > tst <<'!'
86
# shell trap tests
87
#
88
# tst control script that calls tst-1, must be run by ksh
89
# tst-1 calls tst-2
90
# tst-2 calls tst-3
91
# tst-3 defaults or handles and discards/propagates SIGINT
92
#
93
# initial -v option lists script entry and SIGINT delivery
94
#
95
# three test options
96
#
97
# d call next script directly, otherwise via $SHELL -c
98
# t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
99
# x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default
100
# z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default
101
#
102
# Usage: tst [-v] [-options] shell-to-test ...
103
104
# "trap + sig" is an unadvertized extension for this test
105
# if run from nmake SIGINT is set to SIG_IGN
106
# this call sets it back to SIG_DFL
107
# semantics w.r.t. function scope must be worked out before
108
# making it public
109
trap + INT
110
111
set -o monitor
112
113
function gen
114
{
115
typeset o t x d
116
for x in - x z
117
do case $x in
118
[$1]) for t in - t
119
do case $t in
120
[$1]) for d in - d
121
do case $d in
122
[$1]) o="$o $x$t$d"
123
esac
124
done
125
esac
126
done
127
esac
128
done
129
echo '' $o
130
}
131
132
case $1 in
133
-v) v=v; shift ;;
134
-*v*) v=v ;;
135
*) v= ;;
136
esac
137
case $1 in
138
*' '*) o=$1; shift ;;
139
-*) o=$(gen $1); shift ;;
140
*) o=$(gen -txd) ;;
141
esac
142
case $# in
143
0) set ksh bash ksh88 pdksh ash zsh ;;
144
esac
145
for f in $o
146
do case $# in
147
1) ;;
148
*) echo ;;
149
esac
150
for sh
151
do if $sh -c 'exit 0' > /dev/null 2>&1
152
then case $# in
153
1) printf '%3s ' "$f" ;;
154
*) printf '%16s %3s ' "$sh" "$f" ;;
155
esac
156
$sh tst-1 $v$f $sh > tst.out &
157
wait
158
echo $(cat tst.out)
159
fi
160
done
161
done
162
case $# in
163
1) ;;
164
*) echo ;;
165
esac
166
!
167
cat > tst-1 <<'!'
168
exec 2>/dev/null
169
case $1 in
170
*v*) echo 1-main ;;
171
esac
172
{
173
sleep 2
174
case $1 in
175
*v*) echo "SIGINT" ;;
176
esac
177
kill -s INT 0
178
} &
179
case $1 in
180
*t*) trap '
181
echo 1-intr
182
trap - INT
183
# omitting the self kill exposes shells that deliver
184
# the SIGINT trap but exit 0 for -xt
185
# kill -s INT $$
186
' INT
187
;;
188
esac
189
case $1 in
190
*d*) tst-2 $1 $2; status=$? ;;
191
*) $2 -c "tst-2 $1 $2"; status=$? ;;
192
esac
193
printf '1-%04d\n' $status
194
sleep 2
195
!
196
cat > tst-2 <<'!'
197
case $1 in
198
*z*) trap '
199
echo 2-intr
200
exit 0
201
' INT
202
;;
203
*x*) trap '
204
echo 2-intr
205
exit
206
' INT
207
;;
208
*t*) trap '
209
echo 2-intr
210
trap - INT
211
kill -s INT $$
212
' INT
213
;;
214
esac
215
case $1 in
216
*v*) echo 2-main ;;
217
esac
218
case $1 in
219
*d*) tst-3 $1 $2; status=$? ;;
220
*) $2 -c "tst-3 $1 $2"; status=$? ;;
221
esac
222
printf '2-%04d\n' $status
223
!
224
cat > tst-3 <<'!'
225
case $1 in
226
*[xz]*) trap '
227
sleep 2
228
echo 3-intr
229
exit 0
230
' INT
231
;;
232
*) trap '
233
sleep 2
234
echo 3-intr
235
trap - INT
236
kill -s INT $$
237
' INT
238
;;
239
esac
240
case $1 in
241
*v*) echo 3-main ;;
242
esac
243
sleep 5
244
printf '3-%04d\n' $?
245
!
246
chmod +x tst tst-?
247
248
# end standalone test generation
249
250
export PATH=$PATH:
251
typeset -A expected
252
expected[---]="3-intr"
253
expected[--d]="3-intr"
254
expected[-t-]="3-intr 2-intr 1-intr 1-0258"
255
expected[-td]="3-intr 2-intr 1-intr 1-0258"
256
expected[x--]="3-intr 2-intr 1-0000"
257
expected[x-d]="3-intr 2-intr 1-0000"
258
expected[xt-]="3-intr 2-intr 1-intr 1-0000"
259
expected[xtd]="3-intr 2-intr 1-intr 1-0000"
260
expected[z--]="3-intr 2-intr 1-0000"
261
expected[z-d]="3-intr 2-intr 1-0000"
262
expected[zt-]="3-intr 2-intr 1-intr 1-0000"
263
expected[ztd]="3-intr 2-intr 1-intr 1-0000"
264
265
tst $SHELL > tst.got
266
267
while read ops out
268
do [[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'"
269
done < tst.got
270
271
if [[ ${SIG[USR1]} ]]
272
then float s=$SECONDS
273
[[ $(LC_ALL=C $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'
274
(( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
275
((s = SECONDS))
276
[[ $(LC_ALL=C $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'
277
(( SECONDS-s < 4 )) && err_exit 'parent completes early'
278
fi
279
280
yes=$(whence -p yes)
281
if [[ $yes ]]
282
then for exp in TERM VTALRM PIPE
283
do if [[ ${SIG[$exp]} ]]
284
then {
285
$SHELL <<- EOF
286
foo() { return 0; }
287
trap foo EXIT
288
{ sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } &
289
$yes |
290
while read yes
291
do (/bin/date; sleep .1)
292
done > /dev/null
293
EOF
294
} 2>> /dev/null
295
got=$(kill -l $?)
296
[[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'"
297
fi
298
done
299
fi
300
301
SECONDS=0
302
$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig
303
e=$?
304
[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
305
x=$(<$tmp/sig)
306
[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
307
(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
308
309
SECONDS=0
310
$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig
311
e=$?
312
[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
313
x=$(<$tmp/sig)
314
[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
315
(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
316
317
SECONDS=0
318
{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig ;} 2> /dev/null
319
e=$?
320
[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
321
x=$(<$tmp/sig)
322
[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
323
(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
324
325
SECONDS=0
326
{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig ;} 2> /dev/null
327
e=$?
328
[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
329
x=$(<$tmp/sig)
330
[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
331
(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
332
333
SECONDS=0
334
x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished')
335
e=$?
336
[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
337
[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
338
(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
339
340
SECONDS=0
341
x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished')
342
e=$?
343
[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
344
[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
345
(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
346
347
trap '' SIGBUS
348
[[ $($SHELL -c 'trap date SIGBUS; trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap'
349
trap -- - SIGBUS
350
351
{
352
x=$(
353
$SHELL <<- \++EOF
354
timeout()
355
{
356
trap 'trap - TERM; return' TERM
357
( sleep $1; kill -TERM $$ ) >/dev/null 2>&1 &
358
sleep 3
359
}
360
timeout 1
361
print ok
362
++EOF
363
)
364
} 2> /dev/null
365
[[ $x == ok ]] || err_exit 'return without arguments in trap not preserving exit status'
366
367
x=$(
368
$SHELL <<- \++EOF
369
set -o pipefail
370
foobar()
371
{
372
for ((i=0; i < 10000; i++))
373
do print abcdefghijklmnopqrstuvwxyz
374
done | head > /dev/null
375
}
376
foobar
377
print ok
378
++EOF
379
)
380
[[ $x == ok ]] || err_exit 'SIGPIPE exit status causes PIPE signal to be propogaged'
381
382
x=$(
383
$SHELL <<- \EOF
384
trap "print GNAW" URG
385
print 1
386
( sleep 1 ; kill -URG $$ ; sleep 1 ; print S1 ; )
387
print 2
388
EOF
389
)
390
[[ $x == $'1\nS1\nGNAW\n2' ]] || err_exit 'signal ignored in subshell not propagated to parent'
391
392
if [[ ${SIG[RTMIN]} ]]
393
then {
394
$SHELL <<- \EOF
395
trap : RTMIN
396
for ((i=0 ; i < 3 ; i++))
397
do sleep 1
398
kill -RTMIN $$ 2> /dev/null
399
done &
400
wait
401
EOF
402
} 2> /dev/null
403
[[ $? == 0 ]] && err_exit 'wait interrupted by caught signal should have non-zero exit status'
404
{
405
$SHELL <<- \EOF
406
for ((i=0 ; i < 3 ; i++))
407
do sleep 1
408
kill -RTMIN $$ 2> /dev/null
409
done &
410
wait
411
EOF
412
} 2> /dev/null
413
[[ $(kill -l $?) == RTMIN ]] || err_exit 'wait interrupted by signal not caught should exit with the value of that signal+256'
414
fi
415
416
function b
417
{
418
sleep 3
419
endb=1
420
}
421
422
function a
423
{
424
trap 'print int' TERM
425
b
426
enda=1
427
}
428
429
{ /bin/sleep 1;kill -s TERM $$;}&
430
unset enda endb
431
a
432
[[ $endb ]] && err_exit 'TERM signal did not kill function b'
433
[[ $enda == 1 ]] || err_exit 'TERM signal killed function a'
434
435
exit $((Errors<125?Errors:125))
436
437