1 |
# builtin-trap.test.sh |
2 |
|
3 |
#### trap -l |
4 |
trap -l | grep INT >/dev/null |
5 |
## status: 0 |
6 |
## N-I dash/mksh status: 1 |
7 |
|
8 |
#### trap accepts/ignores -- |
9 |
trap -- 'echo hi' EXIT |
10 |
echo done |
11 |
## STDOUT: |
12 |
done |
13 |
hi |
14 |
## END |
15 |
|
16 |
#### trap 'echo hi' KILL (regression test, caught by smoosh suite) |
17 |
trap 'echo hi' 9 |
18 |
echo status=$? |
19 |
trap 'echo hi' KILL |
20 |
echo status=$? |
21 |
trap 'echo hi' STOP |
22 |
echo status=$? |
23 |
trap 'echo hi' TERM |
24 |
echo status=$? |
25 |
## STDOUT: |
26 |
status=0 |
27 |
status=0 |
28 |
status=0 |
29 |
status=0 |
30 |
## END |
31 |
## OK osh STDOUT: |
32 |
status=1 |
33 |
status=1 |
34 |
status=1 |
35 |
status=0 |
36 |
## END |
37 |
|
38 |
#### trap -p |
39 |
trap 'echo exit' EXIT |
40 |
trap -p | grep EXIT >/dev/null |
41 |
## status: 0 |
42 |
## N-I dash/mksh status: 1 |
43 |
|
44 |
#### Register invalid trap |
45 |
trap 'foo' SIGINVALID |
46 |
## status: 1 |
47 |
|
48 |
#### Remove invalid trap |
49 |
trap - SIGINVALID |
50 |
## status: 1 |
51 |
|
52 |
#### SIGINT and INT are aliases |
53 |
trap - SIGINT |
54 |
echo $? |
55 |
trap - INT |
56 |
echo $? |
57 |
## STDOUT: |
58 |
0 |
59 |
0 |
60 |
## END |
61 |
## N-I dash STDOUT: |
62 |
1 |
63 |
0 |
64 |
## END |
65 |
|
66 |
#### Invalid trap invocation |
67 |
trap 'foo' |
68 |
echo status=$? |
69 |
## stdout: status=2 |
70 |
## OK dash stdout: status=1 |
71 |
## BUG mksh stdout: status=0 |
72 |
|
73 |
#### exit 1 when trap code string is invalid |
74 |
# All shells spew warnings to stderr, but don't actually exit! Bad! |
75 |
trap 'echo <' EXIT |
76 |
echo status=$? |
77 |
## stdout: status=1 |
78 |
## BUG mksh status: 1 |
79 |
## BUG mksh stdout: status=0 |
80 |
## BUG dash/bash status: 0 |
81 |
## BUG dash/bash stdout: status=0 |
82 |
|
83 |
#### trap EXIT calling exit |
84 |
cleanup() { |
85 |
echo "cleanup [$@]" |
86 |
exit 42 |
87 |
} |
88 |
trap 'cleanup x y z' EXIT |
89 |
## stdout: cleanup [x y z] |
90 |
## status: 42 |
91 |
|
92 |
#### trap EXIT return status ignored |
93 |
cleanup() { |
94 |
echo "cleanup [$@]" |
95 |
return 42 |
96 |
} |
97 |
trap 'cleanup x y z' EXIT |
98 |
## stdout: cleanup [x y z] |
99 |
## status: 0 |
100 |
|
101 |
#### trap EXIT with PARSE error |
102 |
trap 'echo FAILED' EXIT |
103 |
for |
104 |
## stdout: FAILED |
105 |
## status: 2 |
106 |
## OK mksh status: 1 |
107 |
|
108 |
#### trap EXIT with PARSE error and explicit exit |
109 |
trap 'echo FAILED; exit 0' EXIT |
110 |
for |
111 |
## stdout: FAILED |
112 |
## status: 0 |
113 |
|
114 |
#### trap DEBUG |
115 |
debuglog() { |
116 |
echo "debuglog [$@]" |
117 |
} |
118 |
trap 'debuglog x y' DEBUG |
119 |
echo 1 |
120 |
echo 2 |
121 |
## STDOUT: |
122 |
debuglog [x y] |
123 |
1 |
124 |
debuglog [x y] |
125 |
2 |
126 |
## END |
127 |
## N-I dash/mksh STDOUT: |
128 |
1 |
129 |
2 |
130 |
## END |
131 |
|
132 |
#### trap DEBUG and pipeline |
133 |
case $SH in (dash|mksh) exit 1 ;; esac |
134 |
|
135 |
debuglog() { |
136 |
echo " [$@]" |
137 |
} |
138 |
trap 'debuglog $LINENO' DEBUG |
139 |
|
140 |
# gets run for each one of these |
141 |
{ echo a; echo b; } |
142 |
|
143 |
# only run for the last one |
144 |
{ echo x; echo y; } | wc -l |
145 |
|
146 |
# gets run for both of these |
147 |
date | wc -l |
148 |
|
149 |
date | |
150 |
wc -l |
151 |
|
152 |
## STDOUT: |
153 |
[6] |
154 |
a |
155 |
[6] |
156 |
b |
157 |
[7] |
158 |
2 |
159 |
[8] |
160 |
[8] |
161 |
1 |
162 |
[9] |
163 |
[10] |
164 |
1 |
165 |
## END |
166 |
## N-I dash/mksh status: 1 |
167 |
## N-I dash/mksh stdout-json: "" |
168 |
|
169 |
|
170 |
#### trap DEBUG with compound commands |
171 |
case $SH in (dash|mksh) exit 1 ;; esac |
172 |
|
173 |
# I'm not sure if the observed behavior actually matches the bash documentation |
174 |
# ... |
175 |
# |
176 |
# https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html#Bourne-Shell-Builtins |
177 |
# |
178 |
# "If a sigspec is DEBUG, the command arg is executed before every simple |
179 |
# command, for command, case command, select command, every arithmetic for |
180 |
# command, and before the first command executes in a shell function." |
181 |
|
182 |
debuglog() { |
183 |
echo " [$@]" |
184 |
} |
185 |
trap 'debuglog $LINENO' DEBUG |
186 |
|
187 |
f() { |
188 |
local mylocal=1 |
189 |
for i in "$@"; do |
190 |
export i=$i |
191 |
done |
192 |
} |
193 |
|
194 |
echo '-- assign --' |
195 |
g=1 # executes ONCE here |
196 |
|
197 |
echo '-- function call --' |
198 |
f A B C # executes ONCE here, but does NOT go into th efunction call |
199 |
|
200 |
|
201 |
echo '-- for --' |
202 |
# why does it execute twice here? because of the for loop? That's not a |
203 |
# simple command. |
204 |
for i in 1 2; do |
205 |
echo for1 $i |
206 |
echo for2 $i |
207 |
done |
208 |
|
209 |
echo '-- while --' |
210 |
i=0 |
211 |
while (( i < 2 )); do |
212 |
echo while1 |
213 |
echo while2 |
214 |
(( i++ )) |
215 |
done |
216 |
|
217 |
echo '-- if --' |
218 |
if true; then |
219 |
echo IF |
220 |
fi |
221 |
|
222 |
echo '-- case --' |
223 |
case x in |
224 |
(x) |
225 |
echo CASE |
226 |
esac |
227 |
|
228 |
## STDOUT: |
229 |
[12] |
230 |
-- assign -- |
231 |
[13] |
232 |
[14] |
233 |
-- function call -- |
234 |
[15] |
235 |
[16] |
236 |
-- for -- |
237 |
[17] |
238 |
[18] |
239 |
for1 1 |
240 |
[19] |
241 |
for2 1 |
242 |
[17] |
243 |
[18] |
244 |
for1 2 |
245 |
[19] |
246 |
for2 2 |
247 |
[21] |
248 |
-- while -- |
249 |
[22] |
250 |
[23] |
251 |
[24] |
252 |
while1 |
253 |
[25] |
254 |
while2 |
255 |
[26] |
256 |
[23] |
257 |
[24] |
258 |
while1 |
259 |
[25] |
260 |
while2 |
261 |
[26] |
262 |
[23] |
263 |
[28] |
264 |
-- if -- |
265 |
[29] |
266 |
[30] |
267 |
IF |
268 |
[32] |
269 |
-- case -- |
270 |
[33] |
271 |
[35] |
272 |
CASE |
273 |
## END |
274 |
## N-I dash/mksh status: 1 |
275 |
## N-I dash/mksh stdout-json: "" |
276 |
|
277 |
|
278 |
#### trap RETURN |
279 |
profile() { |
280 |
echo "profile [$@]" |
281 |
} |
282 |
g() { |
283 |
echo -- |
284 |
echo g |
285 |
echo -- |
286 |
return |
287 |
} |
288 |
f() { |
289 |
echo -- |
290 |
echo f |
291 |
echo -- |
292 |
g |
293 |
} |
294 |
# RETURN trap doesn't fire when a function returns, only when a script returns? |
295 |
# That's not what the manual syas. |
296 |
trap 'profile x y' RETURN |
297 |
f |
298 |
. $REPO_ROOT/spec/testdata/return-helper.sh |
299 |
## status: 42 |
300 |
## STDOUT: |
301 |
-- |
302 |
f |
303 |
-- |
304 |
-- |
305 |
g |
306 |
-- |
307 |
return-helper.sh |
308 |
profile [x y] |
309 |
## END |
310 |
## N-I dash/mksh STDOUT: |
311 |
-- |
312 |
f |
313 |
-- |
314 |
-- |
315 |
g |
316 |
-- |
317 |
return-helper.sh |
318 |
## END |
319 |
|
320 |
#### trap ERR and disable it |
321 |
err() { |
322 |
echo "err [$@] $?" |
323 |
} |
324 |
trap 'err x y' ERR |
325 |
echo 1 |
326 |
false |
327 |
echo 2 |
328 |
trap - ERR # disable trap |
329 |
false |
330 |
echo 3 |
331 |
## STDOUT: |
332 |
1 |
333 |
err [x y] 1 |
334 |
2 |
335 |
3 |
336 |
## END |
337 |
## N-I dash STDOUT: |
338 |
1 |
339 |
2 |
340 |
3 |
341 |
## END |
342 |
|
343 |
#### trap 0 is equivalent to EXIT |
344 |
# not sure why this is, but POSIX wants it. |
345 |
trap 'echo EXIT' 0 |
346 |
echo status=$? |
347 |
trap - EXIT |
348 |
echo status=$? |
349 |
## status: 0 |
350 |
## STDOUT: |
351 |
status=0 |
352 |
status=0 |
353 |
## END |
354 |
|
355 |
#### trap 1 is equivalent to SIGHUP; HUP is equivalent to SIGHUP |
356 |
trap 'echo HUP' SIGHUP |
357 |
echo status=$? |
358 |
trap 'echo HUP' HUP |
359 |
echo status=$? |
360 |
trap 'echo HUP' 1 |
361 |
echo status=$? |
362 |
trap - HUP |
363 |
echo status=$? |
364 |
## status: 0 |
365 |
## STDOUT: |
366 |
status=0 |
367 |
status=0 |
368 |
status=0 |
369 |
status=0 |
370 |
## END |
371 |
## N-I dash STDOUT: |
372 |
status=1 |
373 |
status=0 |
374 |
status=0 |
375 |
status=0 |
376 |
## END |
377 |
|
378 |
#### eval in the exit trap (regression for issue #293) |
379 |
trap 'eval "echo hi"' 0 |
380 |
## STDOUT: |
381 |
hi |
382 |
## END |