1 ## compare_shells: dash bash mksh ash
2 ## oils_failures_allowed: 2
3
4 # builtin-trap.test.sh
5
6 #### trap accepts/ignores --
7 trap -- 'echo hi' EXIT
8 echo done
9 ## STDOUT:
10 done
11 hi
12 ## END
13
14 #### trap 'echo hi' KILL (regression test, caught by smoosh suite)
15 trap 'echo hi' 9
16 echo status=$?
17
18 trap 'echo hi' KILL
19 echo status=$?
20
21 trap 'echo hi' STOP
22 echo status=$?
23
24 trap 'echo hi' TERM
25 echo status=$?
26
27 ## STDOUT:
28 status=0
29 status=0
30 status=0
31 status=0
32 ## END
33 ## OK osh STDOUT:
34 status=1
35 status=1
36 status=1
37 status=0
38 ## END
39
40 #### Register invalid trap
41 trap 'foo' SIGINVALID
42 ## status: 1
43
44 #### Remove invalid trap
45 trap - SIGINVALID
46 ## status: 1
47
48 #### SIGINT and INT are aliases
49 trap - SIGINT
50 echo $?
51 trap - INT
52 echo $?
53 ## STDOUT:
54 0
55 0
56 ## END
57 ## N-I dash STDOUT:
58 1
59 0
60 ## END
61
62 #### Invalid trap invocation
63 trap 'foo'
64 echo status=$?
65 ## STDOUT:
66 status=2
67 ## END
68 ## OK dash/ash STDOUT:
69 status=1
70 ## END
71 ## BUG mksh STDOUT:
72 status=0
73 ## END
74
75 #### exit 1 when trap code string is invalid
76 # All shells spew warnings to stderr, but don't actually exit! Bad!
77 trap 'echo <' EXIT
78 echo status=$?
79 ## STDOUT:
80 status=1
81 ## END
82
83 ## BUG mksh status: 1
84 ## BUG mksh STDOUT:
85 status=0
86 ## END
87
88 ## BUG ash status: 2
89 ## BUG ash STDOUT:
90 status=0
91 ## END
92
93 ## BUG dash/bash status: 0
94 ## BUG dash/bash STDOUT:
95 status=0
96 ## END
97
98
99 #### trap EXIT calling exit
100 cleanup() {
101 echo "cleanup [$@]"
102 exit 42
103 }
104 trap 'cleanup x y z' EXIT
105 ## stdout: cleanup [x y z]
106 ## status: 42
107
108 #### trap EXIT return status ignored
109 cleanup() {
110 echo "cleanup [$@]"
111 return 42
112 }
113 trap 'cleanup x y z' EXIT
114 ## stdout: cleanup [x y z]
115 ## status: 0
116
117 #### trap EXIT with PARSE error
118 trap 'echo FAILED' EXIT
119 for
120 ## stdout: FAILED
121 ## status: 2
122 ## OK mksh status: 1
123
124 #### trap EXIT with PARSE error and explicit exit
125 trap 'echo FAILED; exit 0' EXIT
126 for
127 ## stdout: FAILED
128 ## status: 0
129
130 #### trap EXIT with explicit exit
131 trap 'echo IN TRAP; echo $stdout' EXIT
132 stdout=FOO
133 exit 42
134
135 ## status: 42
136 ## STDOUT:
137 IN TRAP
138 FOO
139 ## END
140
141 #### trap EXIT with command sub / subshell / pipeline
142 trap 'echo EXIT TRAP' EXIT
143
144 echo $(echo command sub)
145
146 ( echo subshell )
147
148 echo pipeline | cat
149
150 ## STDOUT:
151 command sub
152 subshell
153 pipeline
154 EXIT TRAP
155 ## END
156
157 #### trap EXIT doesn't run with shopt -s no_fork_last
158
159 # There doesn't seem to be a way to get it to run, so specify that it doesn't
160
161 $SH -c 'trap "echo exit1" EXIT; /bin/true'
162
163 # newline
164 $SH -c 'trap "echo exit2" EXIT; /bin/true
165 '
166
167 # Newline makes a difference!
168 # It doesn't get a chance to run
169 $SH -c 'shopt -s no_fork_last
170 trap "echo exit3" EXIT; /bin/true'
171
172 ## STDOUT:
173 exit1
174 exit2
175 ## END
176
177 ## N-I dash/bash/mksh/ash STDOUT:
178 exit1
179 exit2
180 exit3
181 ## END
182
183 #### trap 0 is equivalent to EXIT
184 # not sure why this is, but POSIX wants it.
185 trap 'echo EXIT' 0
186 echo status=$?
187 trap - EXIT
188 echo status=$?
189 ## status: 0
190 ## STDOUT:
191 status=0
192 status=0
193 ## END
194
195 #### trap 1 is equivalent to SIGHUP; HUP is equivalent to SIGHUP
196 trap 'echo HUP' SIGHUP
197 echo status=$?
198 trap 'echo HUP' HUP
199 echo status=$?
200 trap 'echo HUP' 1
201 echo status=$?
202 trap - HUP
203 echo status=$?
204 ## status: 0
205 ## STDOUT:
206 status=0
207 status=0
208 status=0
209 status=0
210 ## END
211 ## N-I dash STDOUT:
212 status=1
213 status=0
214 status=0
215 status=0
216 ## END
217
218 #### eval in the exit trap (regression for issue #293)
219 trap 'eval "echo hi"' 0
220 ## STDOUT:
221 hi
222 ## END
223
224
225 #### exit codes for traps are isolated
226
227 trap 'echo USR1 trap status=$?; ( exit 42 )' USR1
228
229 echo before=$?
230
231 # Equivalent to 'kill -USR1 $$' except OSH doesn't have "kill" yet.
232 # /bin/kill doesn't exist on Debian unless 'procps' is installed.
233 sh -c "kill -USR1 $$"
234 echo after=$?
235
236 ## STDOUT:
237 before=0
238 USR1 trap status=0
239 after=0
240 ## END
241
242 #### traps are cleared in subshell (started with &)
243
244 # Test with SIGURG because the default handler is SIG_IGN
245 #
246 # If we use SIGUSR1, I think the shell reverts to killing the process
247
248 # https://man7.org/linux/man-pages/man7/signal.7.html
249
250 trap 'echo SIGURG' URG
251
252 kill -URG $$
253
254 # Hm trap doesn't happen here
255 { echo begin child; sleep 0.1; echo end child; } &
256 kill -URG $!
257 wait
258 echo "wait status $?"
259
260 # In the CI, mksh sometimes gives:
261 #
262 # USR1
263 # begin child
264 # done
265 #
266 # leaving off 'end child'. This seems like a BUG to me?
267
268 ## STDOUT:
269 SIGURG
270 begin child
271 end child
272 wait status 0
273 ## END
274
275 #### trap INT, sleep, SIGINT: non-interactively
276
277 # mksh behaves differently in CI -- maybe when it's not connected to a
278 # terminal?
279
280 case $SH in mksh) echo mksh; exit ;; esac
281
282 # Without this, it succeeds in CI?
283 case $SH in *osh) echo osh; exit ;; esac
284
285 $SH -c 'trap "echo int" INT; sleep 0.1' &
286 /usr/bin/kill -INT $!
287 wait
288
289 # Only mksh shows 'int'?
290 # OSH shows "done"
291
292 ## STDOUT:
293 ## END
294 ## OK mksh STDOUT:
295 mksh
296 ## END