1 ## oils_failures_allowed: 5
2 ## compare_shells: bash mksh ash
3
4 # Notes on bash semantics:
5 #
6 # https://www.gnu.org/software/bash/manual/bash.html
7 #
8 # The trap builtin (see Bourne Shell Builtins) allows an ERR pseudo-signal
9 # specification, similar to EXIT and DEBUG. Commands specified with an ERR trap
10 # are executed after a simple command fails, with a few exceptions. The ERR
11 # trap is not inherited by shell functions unless the -o errtrace option to the
12 # set builtin is enabled.
13
14
15 #### trap can use original $LINENO
16
17 trap 'echo line=$LINENO' ERR
18
19 false
20 false
21 echo ok
22
23 ## STDOUT:
24 line=3
25 line=4
26 ok
27 ## END
28
29 #### trap ERR and if statement
30
31 if test -f /nope; then echo file exists; fi
32
33 trap 'echo err' ERR
34 #trap 'echo line=$LINENO' ERR
35
36 if test -f /nope; then echo file exists; fi
37
38 ## STDOUT:
39 ## END
40
41 #### trap ERR does not run in errexit situations
42
43 trap 'echo line=$LINENO' ERR
44
45 if false; then
46 echo if
47 fi
48
49 while false; do
50 echo while
51 done
52
53 until false; do
54 echo until
55 break
56 done
57
58 false || false || false
59
60 false && false && false
61
62 false; false; false
63
64 echo ok
65
66 ## STDOUT:
67 until
68 line=16
69 line=20
70 line=20
71 line=20
72 ok
73 ## END
74
75 #### trap ERR pipeline (also errexit)
76
77 # mksh and bash have different line numbers in this case
78 #trap 'echo line=$LINENO' ERR
79 trap 'echo line=$LINENO' ERR
80
81 # it's run for the last 'false'
82 false | false | false
83
84 { echo pipeline; false; } | false | false
85
86 # it's never run here
87 ! true
88 ! false
89
90 ## STDOUT:
91 line=3
92 line=5
93 ## END
94
95 ## BUG mksh/ash STDOUT:
96 line=1
97 line=1
98 ## END
99
100 #### trap ERR subprogram - subshell, command sub, async
101
102 trap 'echo line=$LINENO' ERR
103
104 ( false; echo subshell )
105
106 x=$( false; echo command sub )
107
108 false & wait
109
110 { false; echo async; } & wait
111
112 false
113 echo ok
114
115 ## STDOUT:
116 subshell
117 async
118 line=11
119 ok
120 ## END
121
122 #### trap ERR not active in shell functions in (bash behavior)
123
124 trap 'echo line=$LINENO' ERR
125
126 f() {
127 false
128 true
129 }
130
131 f
132
133 ## STDOUT:
134 ## END
135
136 ## N-I mksh STDOUT:
137 line=4
138 ## END
139
140 #### trap ERR shell function - with errtrace
141
142 trap 'echo line=$LINENO' ERR
143
144 passing() {
145 false # line 4
146 true
147 }
148
149 failing() {
150 true
151 false
152 }
153
154 passing
155 failing
156
157 set -o errtrace
158
159 echo 'now with errtrace'
160 passing
161 failing
162
163 echo ok
164
165 ## STDOUT:
166 line=14
167 now with errtrace
168 line=4
169 line=10
170 line=20
171 ok
172 ## END
173
174 ## BUG mksh status: 1
175 ## BUG mksh STDOUT:
176 line=4
177 line=10
178 ## END
179
180
181 #### trap ERR with YSH proc
182
183 case $SH in bash|mksh|ash) exit ;; esac
184
185 # seems the same
186
187 shopt -s ysh:upgrade
188
189 proc abc { echo abc }
190 if test -f /nope { echo file exists }
191 trap abc ERR
192 if test -f /nope { echo file exists }
193
194 ## STDOUT:
195 abc
196 ## END
197
198 ## N-I bash/mksh/ash STDOUT:
199 ## END
200
201 #### trap ERR
202 err() {
203 echo "err [$@] $?"
204 }
205 trap 'err x y' ERR
206
207 echo A
208
209 false
210 echo B
211
212 ( exit 42 )
213 echo C
214
215 trap - ERR # disable trap
216
217 false
218 echo D
219
220 trap 'echo after errexit $?' ERR
221
222 set -o errexit
223
224 ( exit 99 )
225 echo E
226
227 ## status: 99
228 ## STDOUT:
229 A
230 err [x y] 1
231 B
232 err [x y] 42
233 C
234 D
235 after errexit 99
236 ## END
237 ## N-I dash STDOUT:
238 A
239 B
240 C
241 D
242 ## END
243
244 #### trap ERR and pipelines (lastpipe and PIPESTATUS difference)
245 case $SH in ash) exit ;; esac
246
247 err() {
248 echo "err [$@] status=$? [${PIPESTATUS[@]}]"
249 }
250 trap 'err' ERR
251
252 echo A
253
254 false
255
256 # succeeds
257 echo B | grep B
258
259 # fails
260 echo C | grep zzz
261
262 echo D | grep zzz | cat
263
264 set -o pipefail
265 echo E | grep zzz | cat
266
267 trap - ERR # disable trap
268
269 echo F | grep zz
270 echo ok
271
272 ## STDOUT:
273 A
274 err [] status=1 [1]
275 B
276 err [] status=1 [0 1]
277 err [] status=1 [0 1 0]
278 ok
279 ## END
280
281 # lastpipe semantics mean we get another call!
282 # also we don't set PIPESTATUS unless we get a pipeline
283
284 ## OK osh STDOUT:
285 A
286 err [] status=1 []
287 B
288 err [] status=1 [0 0]
289 err [] status=1 [0 1]
290 err [] status=1 [0 1 0]
291 ok
292 ## END
293
294 ## N-I ash STDOUT:
295 ## END
296
297 #### error in trap ERR (recursive)
298 case $SH in dash) exit ;; esac
299
300 err() {
301 echo err status $?
302 ( exit 2 )
303 }
304 trap 'err' ERR
305
306 echo A
307 false
308 echo B
309
310 ## STDOUT:
311 A
312 err status 1
313 B
314 ## END
315 ## N-I dash STDOUT:
316 ## END
317