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