1 ## compare_shells: dash bash mksh ash
2 ## oils_failures_allowed: 2
3
4 #### traps are not active inside subshells $() () trap | cat
5
6 # TODO: should we change this? We're not compatible with bash or busybox ash
7
8 trap 'echo bye' EXIT
9
10 # NOT a subshell
11 trap > traps.txt
12 wc -l traps.txt
13
14 echo '( )'
15 ( trap )
16
17 echo '$(trap)'
18 echo $(trap)
19
20 echo 'trap | cat'
21 trap | cat
22
23 ## STDOUT:
24 1 traps.txt
25 ( )
26 $(trap)
27
28 trap | cat
29 bye
30 ## END
31 ## BUG bash STDOUT:
32 1 traps.txt
33 ( )
34 trap -- 'echo bye' EXIT
35 $(trap)
36 trap -- 'echo bye' EXIT
37 trap | cat
38 trap -- 'echo bye' EXIT
39 bye
40 ## END
41 ## BUG-2 ash STDOUT:
42 1 traps.txt
43 ( )
44 $(trap)
45 trap -- 'echo bye' EXIT
46 trap | cat
47 bye
48 ## END
49
50
51 #### trap accepts/ignores --
52 trap -- 'echo hi' EXIT
53 echo ok
54 ## STDOUT:
55 ok
56 hi
57 ## END
58
59 #### Register invalid trap, remove invalid trap
60 trap 'foo' SIGINVALID
61 if test $? -ne 0; then
62 echo ok
63 fi
64
65 trap - SIGINVALID
66 if test $? -ne 0; then
67 echo ok
68 fi
69
70 ## STDOUT:
71 ok
72 ok
73 ## END
74
75 #### trap foo gives non-zero error
76 trap 'foo'
77 if test $? -ne 0; then
78 echo ok
79 fi
80 ## STDOUT:
81 ok
82 ## END
83 ## BUG mksh STDOUT:
84 ## END
85
86 #### SIGINT and INT are aliases
87 trap - SIGINT
88 echo $?
89 trap - INT
90 echo $?
91 ## STDOUT:
92 0
93 0
94 ## END
95 ## N-I dash STDOUT:
96 1
97 0
98 ## END
99
100 #### trap without args prints traps
101 trap 'echo exit' EXIT
102 echo status=$?
103
104 trap
105 echo status=$?
106
107 ## STDOUT:
108 status=0
109 trap -- 'echo exit' EXIT
110 status=0
111 exit
112 ## END
113
114 #### print trap handler with multiple lines
115 trap 'echo 1
116 echo 2
117 echo 3' INT
118
119 trap
120 ## STDOUT:
121 trap -- 'echo 1
122 echo 2
123 echo 3' SIGINT
124 ## END
125 ## OK dash/ash STDOUT:
126 trap -- 'echo 1
127 echo 2
128 echo 3' INT
129 ## END
130 ## OK mksh STDOUT:
131 trap -- $'echo 1\necho 2\necho 3' INT
132 ## END
133
134 #### trap -p is like trap: it prints the handlers and full signal names
135 case $SH in dash) exit ;; esac
136 trap "echo INT" INT
137 trap "echo EXIT" EXIT
138 trap -p
139 ## STDOUT:
140 trap -- 'echo EXIT' EXIT
141 trap -- 'echo INT' SIGINT
142 EXIT
143 ## END
144 ## N-I mksh status: 1
145 ## N-I ash status: 2
146 ## N-I mksh/ash STDOUT:
147 EXIT
148 ## END
149 ## N-I dash STDOUT:
150 ## END
151
152 #### Register the same handler for multiple signals
153 trap 'echo test' TERM 2 EXIT
154 trap
155 ## STDOUT:
156 trap -- 'echo test' EXIT
157 trap -- 'echo test' SIGINT
158 trap -- 'echo test' SIGTERM
159 test
160 ## END
161 ## OK dash/mksh/ash STDOUT:
162 trap -- 'echo test' EXIT
163 trap -- 'echo test' INT
164 trap -- 'echo test' TERM
165 test
166 ## END
167
168 #### Remove multiple handlers with trap -
169 trap "echo int" INT
170 trap "echo e" EXIT
171 trap - int 0 3
172 trap
173
174 echo ---
175 trap "echo int" INT
176 trap "echo e" EXIT
177 trap - int 0 -99
178 if test $? -ne 0; then
179 echo ok
180 fi
181 ## STDOUT:
182 ---
183 ok
184 ## END
185
186 #### trap EXIT clears the EXIT trap
187 trap "echo INT" INT
188 trap "echo EXIT" EXIT
189 trap
190 echo ---
191 trap EXIT
192 trap
193 echo ---
194 trap INT
195 trap
196 ## STDOUT:
197 trap -- 'echo EXIT' EXIT
198 trap -- 'echo INT' SIGINT
199 ---
200 trap -- 'echo INT' SIGINT
201 ---
202 ## END
203 ## OK dash/ash STDOUT:
204 trap -- 'echo EXIT' EXIT
205 trap -- 'echo INT' INT
206 ---
207 trap -- 'echo INT' INT
208 ---
209 ## END
210 ## BUG mksh STDOUT:
211 trap -- 'echo EXIT' EXIT
212 trap -- 'echo INT' INT
213 ---
214 trap -- 'echo EXIT' EXIT
215 trap -- 'echo INT' INT
216 ---
217 trap -- 'echo EXIT' EXIT
218 trap -- 'echo INT' INT
219 EXIT
220 ## END
221
222 #### trap 0 is equivalent to trap EXIT
223 trap "echo INT" INT
224 trap "echo EXIT" 0 # EXIT
225 trap
226 echo ---
227 trap 0
228 trap
229 ## STDOUT:
230 trap -- 'echo EXIT' EXIT
231 trap -- 'echo INT' SIGINT
232 ---
233 trap -- 'echo INT' SIGINT
234 ## END
235 ## OK dash/ash/mksh STDOUT:
236 trap -- 'echo EXIT' EXIT
237 trap -- 'echo INT' INT
238 ---
239 trap -- 'echo INT' INT
240 ## END
241
242 #### trap 1 is equivalent to SIGHUP; HUP is equivalent to SIGHUP
243 trap 'echo HUP' SIGHUP
244 echo status=$?
245 trap 'echo HUP' HUP
246 echo status=$?
247 trap 'echo HUP' 1
248 echo status=$?
249 trap - HUP
250 echo status=$?
251 ## status: 0
252 ## STDOUT:
253 status=0
254 status=0
255 status=0
256 status=0
257 ## END
258 ## N-I dash STDOUT:
259 status=1
260 status=0
261 status=0
262 status=0
263 ## END
264
265 #### trap 0 2 resets EXIT AND SIGINT
266
267 trap "echo EXIT" EXIT
268 echo ---
269 trap
270 echo ---
271 trap 0 2
272 trap
273 echo ---
274 trap "echo INT" INT
275 trap "echo EXIT" EXIT
276 trap 2 EXIT
277 trap
278
279 ## STDOUT:
280 ---
281 trap -- 'echo EXIT' EXIT
282 ---
283 ---
284 ## END
285
286 #### trap '' EXIT - printing state
287
288 trap 'echo exit' EXIT
289 trap
290 echo
291
292 trap '' EXIT
293 trap
294 echo
295
296 trap '# comment' EXIT
297 trap
298
299 ## STDOUT:
300 trap -- 'echo exit' EXIT
301
302 trap -- '' EXIT
303
304 trap -- '# comment' EXIT
305 ## END
306 ## BUG mksh STDOUT:
307 trap -- 'echo exit' EXIT
308
309 trap -- EXIT
310
311 trap -- '# comment' EXIT
312 ## END
313
314 #### trap 'echo hi' KILL (regression test, caught by smoosh suite)
315 trap 'echo hi' 9
316 echo status=$?
317
318 trap 'echo hi' KILL
319 echo status=$?
320
321 trap 'echo hi' STOP
322 echo status=$?
323
324 trap 'echo hi' TERM
325 echo status=$?
326
327 ## STDOUT:
328 status=0
329 status=0
330 status=0
331 status=0
332 ## END
333 ## OK osh STDOUT:
334 status=2
335 status=2
336 status=2
337 status=0
338 ## END
339
340 #### exit 1 when trap code string is invalid
341 # All shells spew warnings to stderr, but don't actually exit! Bad!
342 trap 'echo <' EXIT
343 echo status=$?
344 ## STDOUT:
345 status=1
346 ## END
347
348 ## BUG mksh status: 1
349 ## BUG mksh STDOUT:
350 status=0
351 ## END
352
353 ## BUG ash status: 2
354 ## BUG ash STDOUT:
355 status=0
356 ## END
357
358 ## BUG dash/bash status: 0
359 ## BUG dash/bash STDOUT:
360 status=0
361 ## END
362
363
364 #### trap EXIT calling exit
365 cleanup() {
366 echo "cleanup [$@]"
367 exit 42
368 }
369 trap 'cleanup x y z' EXIT
370 ## stdout: cleanup [x y z]
371 ## status: 42
372
373 #### trap EXIT return status ignored
374 cleanup() {
375 echo "cleanup [$@]"
376 return 42
377 }
378 trap 'cleanup x y z' EXIT
379 ## stdout: cleanup [x y z]
380 ## status: 0
381
382 #### trap EXIT with PARSE error
383 trap 'echo FAILED' EXIT
384 for
385 ## stdout: FAILED
386 ## status: 2
387 ## OK mksh status: 1
388
389 #### trap EXIT with PARSE error and explicit exit
390 trap 'echo FAILED; exit 0' EXIT
391 for
392 ## stdout: FAILED
393 ## status: 0
394
395 #### trap EXIT with explicit exit
396 trap 'echo IN TRAP; echo $stdout' EXIT
397 stdout=FOO
398 exit 42
399
400 ## status: 42
401 ## STDOUT:
402 IN TRAP
403 FOO
404 ## END
405
406 #### trap EXIT with command sub / subshell / pipeline
407 trap 'echo EXIT TRAP' EXIT
408
409 echo $(echo command sub)
410
411 ( echo subshell )
412
413 echo pipeline | cat
414
415 ## STDOUT:
416 command sub
417 subshell
418 pipeline
419 EXIT TRAP
420 ## END
421
422 #### eval in the exit trap (regression for issue #293)
423 trap 'eval "echo hi"' 0
424 ## STDOUT:
425 hi
426 ## END
427
428
429 #### exit codes for traps are isolated
430
431 trap 'echo USR1 trap status=$?; ( exit 42 )' USR1
432
433 echo before=$?
434
435 # Equivalent to 'kill -USR1 $$' except OSH doesn't have "kill" yet.
436 # /bin/kill doesn't exist on Debian unless 'procps' is installed.
437 sh -c "kill -USR1 $$"
438 echo after=$?
439
440 ## STDOUT:
441 before=0
442 USR1 trap status=0
443 after=0
444 ## END
445
446 #### traps are cleared in subshell (started with &)
447
448 # Test with SIGURG because the default handler is SIG_IGN
449 #
450 # If we use SIGUSR1, I think the shell reverts to killing the process
451
452 # https://man7.org/linux/man-pages/man7/signal.7.html
453
454 trap 'echo SIGURG' URG
455
456 kill -URG $$
457
458 # Hm trap doesn't happen here
459 { echo begin child; sleep 0.1; echo end child; } &
460 kill -URG $!
461 wait
462 echo "wait status $?"
463
464 # In the CI, mksh sometimes gives:
465 #
466 # USR1
467 # begin child
468 # done
469 #
470 # leaving off 'end child'. This seems like a BUG to me?
471
472 ## STDOUT:
473 SIGURG
474 begin child
475 end child
476 wait status 0
477 ## END
478
479 #### trap USR1, sleep, SIGINT: non-interactively
480
481 $REPO_ROOT/spec/testdata/builtin-trap-usr1.sh
482
483 ## STDOUT:
484 usr1
485 status=0
486 ## END
487
488 #### trap INT, sleep, SIGINT: non-interactively
489
490 # mksh behaves differently in CI -- maybe when it's not connected to a
491 # terminal?
492 case $SH in mksh) echo mksh; exit ;; esac
493
494 $REPO_ROOT/spec/testdata/builtin-trap-int.sh
495
496 ## STDOUT:
497 status=0
498 ## END
499
500 ## OK mksh STDOUT:
501 mksh
502 ## END
503
504 # Not sure why other shells differ here, but running the trap is consistent
505 # with interactive cases in test/bugs.sh
506
507 ## OK osh STDOUT:
508 int
509 status=0
510 ## END
511
512 #### trap EXIT, sleep, SIGINT: non-interactively
513
514 $REPO_ROOT/spec/testdata/builtin-trap-exit.sh
515
516 ## STDOUT:
517 on exit
518 status=0
519 ## END
520
521 #### Remove trap with an unsigned integer
522
523 $SH -e -c '
524 trap "echo noprint" EXIT
525 trap 0 EXIT
526 echo ok0
527 '
528 echo
529
530 $SH -e -c '
531 trap "echo noprint" EXIT
532 trap " 42 " EXIT
533 echo ok42space
534 '
535 echo
536
537 # corner case: sometimes 07 is treated as octal, but not here
538 $SH -e -c '
539 trap "echo noprint" EXIT
540 trap 07 EXIT
541 echo ok07
542 '
543 echo
544
545 $SH -e -c '
546 trap "echo trap-exit" EXIT
547 trap -1 EXIT
548 echo bad
549 '
550 if test $? -ne 0; then
551 echo failure
552 fi
553
554 ## STDOUT:
555 ok0
556
557 ok42space
558
559 ok07
560
561 trap-exit
562 failure
563 ## END