1 #!/bin/bash
2 #
3 # Cases relevant to set -o strict-errexit in OSH.
4 #
5 # Summary:
6 # - errexit is reset to false in ash/bash -- completely ignored!
7 # - local assignment is different than global! The exit code and errexit
8 # behavior are different because the concept of the "last command" is
9 # different.
10 # - ash has copied bash behavior!
11
12 ### command sub: errexit ignored
13 # This is the bash-specific bug here:
14 # https://blogs.janestreet.com/when-bash-scripts-bite/
15 # In bash 4.4, inherit_errexit should fix this.
16 set -o errexit
17 echo $(echo one; false; echo two) # bash/ash keep going
18 echo status=$?
19 ## STDOUT:
20 one two
21 status=0
22 ## END
23 # dash and mksh: inner shell aborts, but outer one keeps going!
24 ## OK dash/mksh STDOUT:
25 one
26 status=0
27 ## END
28
29 ### command sub: errexit not ignored with strict-errexit
30 set -o errexit
31 set -o strict-errexit || true
32 echo zero
33 echo $(echo one; false; echo two) # bash/ash keep going
34 echo status=$?
35 ## STDOUT:
36 zero
37 ## END
38 ## status: 1
39 ## N-I dash status: 2
40 ## N-I dash stdout-json: ""
41 ## N-I mksh stdout-json: ""
42 ## N-I ash/bash status: 0
43 ## N-I ash/bash STDOUT:
44 zero
45 one two
46 status=0
47 ## END
48
49 ### command sub: last command fails but keeps going and exit code is 0
50 set -o errexit
51 echo $(echo one; false) # we lost the exit code
52 echo status=$?
53 ## STDOUT:
54 one
55 status=0
56 ## END
57
58 ### global assignment with command sub: middle command fails
59 set -o errexit
60 s=$(echo one; false; echo two;)
61 echo "$s"
62 ## status: 0
63 ## STDOUT:
64 one
65 two
66 ## END
67 # dash and mksh: whole thing aborts!
68 ## OK dash/mksh stdout-json: ""
69 ## OK dash/mksh status: 1
70
71 ### global assignment with command sub: last command fails and it aborts
72 set -o errexit
73 s=$(echo one; false)
74 echo status=$?
75 ## stdout-json: ""
76 ## status: 1
77
78 ### local: middle command fails and keeps going
79 set -o errexit
80 f() {
81 echo good
82 local x=$(echo one; false; echo two)
83 echo status=$?
84 echo $x
85 }
86 f
87 ## STDOUT:
88 good
89 status=0
90 one two
91 ## END
92 # for dash and mksh, the INNER shell aborts, but the outer one keeps going!
93 ## OK dash/mksh STDOUT:
94 good
95 status=0
96 one
97 ## END
98
99 ### local: last command fails and also keeps going
100 set -o errexit
101 f() {
102 echo good
103 local x=$(echo one; false)
104 echo status=$?
105 echo $x
106 }
107 f
108 ## STDOUT:
109 good
110 status=0
111 one
112 ## END
113
114 ### local and strict-errexit
115 # I've run into this problem a lot.
116 set -o errexit
117 set -o strict-errexit || true # ignore error
118 f() {
119 echo good
120 local x=$(echo one; false; echo two)
121 echo status=$?
122 echo $x
123 }
124 f
125 # status: 1
126 ## STDOUT:
127 good
128 ## END
129 ## N-I bash/ash status: 0
130 ## N-I bash/ash STDOUT:
131 good
132 status=0
133 one two
134 ## END
135 ## N-I dash status: 2
136 ## N-I dash stdout-json: ""
137 ## N-I mksh status: 1
138 ## N-I mksh stdout-json: ""
139
140 ### global assignment when last status is failure
141 # this is a bug I introduced
142 set -o errexit
143 [ -n "${BUILDDIR+x}" ] && _BUILDDIR=$BUILDDIR
144 BUILDDIR=${_BUILDDIR-$BUILDDIR}
145 echo status=$?
146 ## STDOUT:
147 status=0
148 ## END
149
150 ### global assignment when last status is failure
151 # this is a bug I introduced
152 set -o errexit
153 x=$(false) || true # from abuild
154 [ -n "$APORTSDIR" ] && true
155 BUILDDIR=${_BUILDDIR-$BUILDDIR}
156 echo status=$?
157 ## STDOUT:
158 status=0
159 ## END