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
|