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 EXIT with explicit exit |
115 |
trap 'echo IN TRAP; echo $stdout' EXIT |
116 |
stdout=FOO |
117 |
exit 42 |
118 |
|
119 |
## status: 42 |
120 |
## STDOUT: |
121 |
IN TRAP |
122 |
FOO |
123 |
## END |
124 |
|
125 |
#### trap DEBUG |
126 |
debuglog() { |
127 |
echo "debuglog [$@]" |
128 |
} |
129 |
trap 'debuglog x y' DEBUG |
130 |
echo 1 |
131 |
echo 2 |
132 |
## STDOUT: |
133 |
debuglog [x y] |
134 |
1 |
135 |
debuglog [x y] |
136 |
2 |
137 |
## END |
138 |
## N-I dash/mksh STDOUT: |
139 |
1 |
140 |
2 |
141 |
## END |
142 |
|
143 |
#### trap DEBUG and pipeline |
144 |
case $SH in (dash|mksh) exit 1 ;; esac |
145 |
|
146 |
debuglog() { |
147 |
echo " [$@]" |
148 |
} |
149 |
trap 'debuglog $LINENO' DEBUG |
150 |
|
151 |
# gets run for each one of these |
152 |
{ echo a; echo b; } |
153 |
|
154 |
# only run for the last one |
155 |
{ echo x; echo y; } | wc -l |
156 |
|
157 |
# gets run for both of these |
158 |
date | wc -l |
159 |
|
160 |
date | |
161 |
wc -l |
162 |
|
163 |
## STDOUT: |
164 |
[8] |
165 |
a |
166 |
[8] |
167 |
b |
168 |
[10] |
169 |
2 |
170 |
[12] |
171 |
[12] |
172 |
1 |
173 |
[14] |
174 |
[15] |
175 |
1 |
176 |
## END |
177 |
## N-I dash/mksh status: 1 |
178 |
## N-I dash/mksh stdout-json: "" |
179 |
|
180 |
|
181 |
#### trap DEBUG with compound commands |
182 |
case $SH in (dash|mksh) exit 1 ;; esac |
183 |
|
184 |
# I'm not sure if the observed behavior actually matches the bash documentation |
185 |
# ... |
186 |
# |
187 |
# https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html#Bourne-Shell-Builtins |
188 |
# |
189 |
# "If a sigspec is DEBUG, the command arg is executed before every simple |
190 |
# command, for command, case command, select command, every arithmetic for |
191 |
# command, and before the first command executes in a shell function." |
192 |
|
193 |
debuglog() { |
194 |
echo " [$@]" |
195 |
} |
196 |
trap 'debuglog $LINENO' DEBUG |
197 |
|
198 |
f() { |
199 |
local mylocal=1 |
200 |
for i in "$@"; do |
201 |
export i=$i |
202 |
done |
203 |
} |
204 |
|
205 |
echo '-- assign --' |
206 |
g=1 # executes ONCE here |
207 |
|
208 |
echo '-- function call --' |
209 |
f A B C # executes ONCE here, but does NOT go into th efunction call |
210 |
|
211 |
|
212 |
echo '-- for --' |
213 |
# why does it execute twice here? because of the for loop? That's not a |
214 |
# simple command. |
215 |
for i in 1 2; do |
216 |
echo for1 $i |
217 |
echo for2 $i |
218 |
done |
219 |
|
220 |
echo '-- while --' |
221 |
i=0 |
222 |
while (( i < 2 )); do |
223 |
echo while1 |
224 |
echo while2 |
225 |
(( i++ )) |
226 |
done |
227 |
|
228 |
echo '-- if --' |
229 |
if true; then |
230 |
echo IF |
231 |
fi |
232 |
|
233 |
echo '-- case --' |
234 |
case x in |
235 |
(x) |
236 |
echo CASE |
237 |
esac |
238 |
|
239 |
## STDOUT: |
240 |
[16] |
241 |
-- assign -- |
242 |
[17] |
243 |
[19] |
244 |
-- function call -- |
245 |
[20] |
246 |
[23] |
247 |
-- for -- |
248 |
[24] |
249 |
[25] |
250 |
for1 1 |
251 |
[26] |
252 |
for2 1 |
253 |
[24] |
254 |
[25] |
255 |
for1 2 |
256 |
[26] |
257 |
for2 2 |
258 |
[29] |
259 |
-- while -- |
260 |
[30] |
261 |
[31] |
262 |
[32] |
263 |
while1 |
264 |
[33] |
265 |
while2 |
266 |
[34] |
267 |
[31] |
268 |
[32] |
269 |
while1 |
270 |
[33] |
271 |
while2 |
272 |
[34] |
273 |
[31] |
274 |
[37] |
275 |
-- if -- |
276 |
[38] |
277 |
[39] |
278 |
IF |
279 |
[42] |
280 |
-- case -- |
281 |
[43] |
282 |
[45] |
283 |
CASE |
284 |
## END |
285 |
## N-I dash/mksh status: 1 |
286 |
## N-I dash/mksh stdout-json: "" |
287 |
|
288 |
|
289 |
#### trap RETURN |
290 |
profile() { |
291 |
echo "profile [$@]" |
292 |
} |
293 |
g() { |
294 |
echo -- |
295 |
echo g |
296 |
echo -- |
297 |
return |
298 |
} |
299 |
f() { |
300 |
echo -- |
301 |
echo f |
302 |
echo -- |
303 |
g |
304 |
} |
305 |
# RETURN trap doesn't fire when a function returns, only when a script returns? |
306 |
# That's not what the manual syas. |
307 |
trap 'profile x y' RETURN |
308 |
f |
309 |
. $REPO_ROOT/spec/testdata/return-helper.sh |
310 |
## status: 42 |
311 |
## STDOUT: |
312 |
-- |
313 |
f |
314 |
-- |
315 |
-- |
316 |
g |
317 |
-- |
318 |
return-helper.sh |
319 |
profile [x y] |
320 |
## END |
321 |
## N-I dash/mksh STDOUT: |
322 |
-- |
323 |
f |
324 |
-- |
325 |
-- |
326 |
g |
327 |
-- |
328 |
return-helper.sh |
329 |
## END |
330 |
|
331 |
#### trap ERR and disable it |
332 |
err() { |
333 |
echo "err [$@] $?" |
334 |
} |
335 |
trap 'err x y' ERR |
336 |
echo 1 |
337 |
false |
338 |
echo 2 |
339 |
trap - ERR # disable trap |
340 |
false |
341 |
echo 3 |
342 |
## STDOUT: |
343 |
1 |
344 |
err [x y] 1 |
345 |
2 |
346 |
3 |
347 |
## END |
348 |
## N-I dash STDOUT: |
349 |
1 |
350 |
2 |
351 |
3 |
352 |
## END |
353 |
|
354 |
#### trap 0 is equivalent to EXIT |
355 |
# not sure why this is, but POSIX wants it. |
356 |
trap 'echo EXIT' 0 |
357 |
echo status=$? |
358 |
trap - EXIT |
359 |
echo status=$? |
360 |
## status: 0 |
361 |
## STDOUT: |
362 |
status=0 |
363 |
status=0 |
364 |
## END |
365 |
|
366 |
#### trap 1 is equivalent to SIGHUP; HUP is equivalent to SIGHUP |
367 |
trap 'echo HUP' SIGHUP |
368 |
echo status=$? |
369 |
trap 'echo HUP' HUP |
370 |
echo status=$? |
371 |
trap 'echo HUP' 1 |
372 |
echo status=$? |
373 |
trap - HUP |
374 |
echo status=$? |
375 |
## status: 0 |
376 |
## STDOUT: |
377 |
status=0 |
378 |
status=0 |
379 |
status=0 |
380 |
status=0 |
381 |
## END |
382 |
## N-I dash STDOUT: |
383 |
status=1 |
384 |
status=0 |
385 |
status=0 |
386 |
status=0 |
387 |
## END |
388 |
|
389 |
#### eval in the exit trap (regression for issue #293) |
390 |
trap 'eval "echo hi"' 0 |
391 |
## STDOUT: |
392 |
hi |
393 |
## END |
394 |
|
395 |
|
396 |
#### exit codes for traps are isolated |
397 |
trap 'echo USR1 trap status=$?; ( exit 42 )' USR1 |
398 |
|
399 |
echo before=$? |
400 |
|
401 |
# Equivalent to 'kill -USR1 $$' except OSH doesn't have "kill" yet. |
402 |
# /bin/kill doesn't exist on Debian unless 'procps' is installed. |
403 |
sh -c "kill -USR1 $$" |
404 |
echo after=$? |
405 |
|
406 |
## STDOUT: |
407 |
before=0 |
408 |
USR1 trap status=0 |
409 |
after=0 |
410 |
## END |