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