1 | ## oils_failures_allowed: 3
|
2 | ## compare_shells: dash bash mksh
|
3 |
|
4 | # Job control constructs:
|
5 | # & terminator (instead of ;)
|
6 | # $! -- last PID
|
7 | # wait builtin (wait -n waits for next)
|
8 | #
|
9 | # Only interactive:
|
10 | # fg
|
11 | # bg
|
12 | # %1 -- current job
|
13 |
|
14 | #### wait with nothing to wait for
|
15 | wait
|
16 | ## status: 0
|
17 |
|
18 | #### wait -n with arguments - arguments are respected
|
19 | case $SH in dash|mksh) exit ;; esac
|
20 |
|
21 | echo x &
|
22 |
|
23 | # here, you can't tell if it's -n or the other
|
24 | wait -n $!
|
25 | echo status=$?
|
26 |
|
27 | # by the bash error, you can tell which is preferred
|
28 | wait -n $! bad 2>err.txt
|
29 | echo status=$?
|
30 | echo
|
31 |
|
32 | n=$(wc -l < err.txt)
|
33 | if test "$n" -gt 0; then
|
34 | echo 'got error lines'
|
35 | fi
|
36 |
|
37 | ## STDOUT:
|
38 | x
|
39 | status=0
|
40 | status=127
|
41 |
|
42 | got error lines
|
43 | ## END
|
44 | ## N-I dash/mksh STDOUT:
|
45 | ## END
|
46 |
|
47 | #### wait -n with nothing to wait for
|
48 | # The 127 is STILL overloaded. Copying bash for now.
|
49 | wait -n
|
50 | ## status: 127
|
51 | ## N-I dash status: 2
|
52 | ## N-I mksh status: 1
|
53 |
|
54 | #### wait with jobspec syntax %nonexistent
|
55 | wait %nonexistent
|
56 | ## status: 127
|
57 | ## OK dash status: 2
|
58 |
|
59 | #### wait with invalid PID
|
60 | wait 12345678
|
61 | ## status: 127
|
62 |
|
63 | #### wait with invalid arg
|
64 | wait zzz
|
65 | ## status: 2
|
66 | ## OK bash status: 1
|
67 | # mksh confuses a syntax error with 'command not found'!
|
68 | ## BUG mksh status: 127
|
69 |
|
70 | #### wait for N parallel jobs
|
71 |
|
72 | for i in 3 2 1; do
|
73 | { sleep 0.0$i; exit $i; } &
|
74 | done
|
75 | wait
|
76 |
|
77 | # status is lost
|
78 | echo status=$?
|
79 |
|
80 | ## STDOUT:
|
81 | status=0
|
82 | ## END
|
83 |
|
84 | #### wait for N parallel jobs and check failure
|
85 |
|
86 | set -o errexit
|
87 |
|
88 | pids=''
|
89 | for i in 3 2 1; do
|
90 | { sleep 0.0$i; echo $i; exit $i; } &
|
91 | pids="$pids $!"
|
92 | done
|
93 |
|
94 | for pid in $pids; do
|
95 | set +o errexit
|
96 | wait $pid
|
97 | status=$?
|
98 | set -o errexit
|
99 |
|
100 | echo status=$status
|
101 | done
|
102 |
|
103 | ## STDOUT:
|
104 | 1
|
105 | 2
|
106 | 3
|
107 | status=3
|
108 | status=2
|
109 | status=1
|
110 | ## END
|
111 |
|
112 | #### Builtin in background
|
113 | echo async &
|
114 | wait
|
115 | ## stdout: async
|
116 |
|
117 | #### External command in background
|
118 | sleep 0.01 &
|
119 | wait
|
120 | ## stdout-json: ""
|
121 |
|
122 | #### Start background pipeline, wait $pid
|
123 | echo hi | { exit 99; } &
|
124 | echo status=$?
|
125 | wait $!
|
126 | echo status=$?
|
127 | echo --
|
128 |
|
129 | pids=''
|
130 | for i in 3 2 1; do
|
131 | sleep 0.0$i | echo i=$i | ( exit $i ) &
|
132 | pids="$pids $!"
|
133 | done
|
134 | #echo "PIDS $pids"
|
135 |
|
136 | for pid in $pids; do
|
137 | wait $pid
|
138 | echo status=$?
|
139 | done
|
140 |
|
141 | # Not cleaned up
|
142 | if false; then
|
143 | echo 'DEBUG'
|
144 | jobs --debug
|
145 | fi
|
146 |
|
147 | ## STDOUT:
|
148 | status=0
|
149 | status=99
|
150 | --
|
151 | status=3
|
152 | status=2
|
153 | status=1
|
154 | ## END
|
155 |
|
156 | #### Start background pipeline, wait %job_spec
|
157 | echo hi | { exit 99; } &
|
158 | echo status=$?
|
159 | wait %1
|
160 | echo status=$?
|
161 | ## STDOUT:
|
162 | status=0
|
163 | status=99
|
164 | ## END
|
165 |
|
166 | #### Wait for job and PIPESTATUS
|
167 |
|
168 | # foreground
|
169 | { echo hi; exit 55; } | false
|
170 | echo fore status=$? pipestatus=${PIPESTATUS[@]}
|
171 |
|
172 | # background
|
173 | { echo hi; exit 44; } | false &
|
174 | echo back status=$? pipestatus=${PIPESTATUS[@]}
|
175 |
|
176 | # wait for pipeline
|
177 | wait %+
|
178 | #wait %1
|
179 | #wait $!
|
180 | echo wait status=$? pipestatus=${PIPESTATUS[@]}
|
181 |
|
182 | ## STDOUT:
|
183 | fore status=1 pipestatus=55 1
|
184 | back status=0 pipestatus=0
|
185 | wait status=1 pipestatus=1
|
186 | ## END
|
187 | ## N-I dash status: 2
|
188 | ## N-I dash STDOUT:
|
189 | ## END
|
190 |
|
191 | #### Wait for job and PIPESTATUS - cat
|
192 |
|
193 | # foreground
|
194 | exit 55 | ( cat; exit 99 )
|
195 | echo fore status=$? pipestatus=${PIPESTATUS[@]}
|
196 |
|
197 | # background
|
198 | exit 44 | ( cat; exit 88 ) &
|
199 | echo back status=$? pipestatus=${PIPESTATUS[@]}
|
200 |
|
201 | # wait for pipeline
|
202 | wait %+
|
203 | #wait %1
|
204 | #wait $!
|
205 | echo wait status=$? pipestatus=${PIPESTATUS[@]}
|
206 | echo
|
207 |
|
208 | # wait for non-pipeline
|
209 | ( exit 77 ) &
|
210 | wait %+
|
211 | echo wait status=$? pipestatus=${PIPESTATUS[@]}
|
212 |
|
213 | ## STDOUT:
|
214 | fore status=99 pipestatus=55 99
|
215 | back status=0 pipestatus=0
|
216 | wait status=88 pipestatus=88
|
217 |
|
218 | wait status=77 pipestatus=77
|
219 | ## END
|
220 | ## N-I dash status: 2
|
221 | ## N-I dash STDOUT:
|
222 | ## END
|
223 |
|
224 | #### Brace group in background, wait all
|
225 | { sleep 0.09; exit 9; } &
|
226 | { sleep 0.07; exit 7; } &
|
227 | wait # wait for all gives 0
|
228 | echo "status=$?"
|
229 | ## stdout: status=0
|
230 |
|
231 | #### Wait on background process PID
|
232 | { sleep 0.09; exit 9; } &
|
233 | pid1=$!
|
234 | { sleep 0.07; exit 7; } &
|
235 | pid2=$!
|
236 | wait $pid2
|
237 | echo "status=$?"
|
238 | wait $pid1
|
239 | echo "status=$?"
|
240 | ## STDOUT:
|
241 | status=7
|
242 | status=9
|
243 | ## END
|
244 |
|
245 | #### Wait on multiple specific IDs returns last status
|
246 | { sleep 0.08; exit 8; } &
|
247 | jid1=$!
|
248 | { sleep 0.09; exit 9; } &
|
249 | jid2=$!
|
250 | { sleep 0.07; exit 7; } &
|
251 | jid3=$!
|
252 | wait $jid1 $jid2 $jid3 # NOTE: not using %1 %2 %3 syntax on purpose
|
253 | echo "status=$?" # third job I think
|
254 | ## stdout: status=7
|
255 |
|
256 | #### wait -n
|
257 | case $SH in (dash|mksh) return ;; esac
|
258 |
|
259 | { sleep 0.09; exit 9; } &
|
260 | { sleep 0.03; exit 3; } &
|
261 | wait -n
|
262 | echo "status=$?"
|
263 | wait -n
|
264 | echo "status=$?"
|
265 | ## STDOUT:
|
266 | status=3
|
267 | status=9
|
268 | ## END
|
269 | ## N-I dash/mksh stdout-json: ""
|
270 |
|
271 | #### Async for loop
|
272 | for i in 1 2 3; do
|
273 | echo $i
|
274 | sleep 0.0$i
|
275 | done &
|
276 | wait
|
277 | ## STDOUT:
|
278 | 1
|
279 | 2
|
280 | 3
|
281 | ## END
|
282 | ## status: 0
|
283 |
|
284 | #### Background process doesn't affect parent
|
285 | echo ${foo=1}
|
286 | echo $foo
|
287 | echo ${bar=2} &
|
288 | wait
|
289 | echo $bar # bar is NOT SET in the parent process
|
290 | ## STDOUT:
|
291 | 1
|
292 | 1
|
293 | 2
|
294 |
|
295 | ## END
|
296 |
|
297 | #### Background process and then a singleton pipeline
|
298 |
|
299 | # This was inspired by #416, although that symptom there was timing, so it's
|
300 | # technically not a regression test. It's hard to test timing.
|
301 |
|
302 | { sleep 0.1; exit 42; } &
|
303 | echo begin
|
304 | ! true
|
305 | echo end
|
306 | wait $!
|
307 | echo status=$?
|
308 | ## STDOUT:
|
309 | begin
|
310 | end
|
311 | status=42
|
312 | ## END
|
313 |
|
314 | #### jobs prints one line per job
|
315 | sleep 0.1 &
|
316 | sleep 0.1 | cat &
|
317 |
|
318 | # dash doesn't print if it's not a terminal?
|
319 | jobs | wc -l
|
320 |
|
321 | ## STDOUT:
|
322 | 2
|
323 | ## END
|
324 | ## BUG dash STDOUT:
|
325 | 0
|
326 | ## END
|
327 |
|
328 | #### jobs -p prints one line per job
|
329 | sleep 0.1 &
|
330 | sleep 0.1 | cat &
|
331 |
|
332 | jobs -p > tmp.txt
|
333 |
|
334 | cat tmp.txt | wc -l # 2 lines, one for each job
|
335 | cat tmp.txt | wc -w # each line is a single "word"
|
336 |
|
337 | ## STDOUT:
|
338 | 2
|
339 | 2
|
340 | ## END
|
341 |
|
342 |
|
343 | #### No stderr spew when shell is not interactive
|
344 |
|
345 | # in interactive shell, this prints 'Process' or 'Pipeline'
|
346 | sleep 0.01 &
|
347 | sleep 0.01 | cat &
|
348 | wait
|
349 |
|
350 | ## STDOUT:
|
351 | ## END
|
352 | ## STDERR:
|
353 | ## END
|
354 |
|
355 |
|
356 | #### YSH wait --all
|
357 | case $SH in dash|bash|mksh) exit ;; esac
|
358 |
|
359 | sleep 0.01 &
|
360 | (exit 55) &
|
361 | true &
|
362 | wait
|
363 | echo wait $?
|
364 |
|
365 | sleep 0.01 &
|
366 | (exit 44) &
|
367 | true &
|
368 | wait --all
|
369 | echo wait --all $?
|
370 |
|
371 | ## STDOUT:
|
372 | wait 0
|
373 | wait --all 1
|
374 | ## END
|
375 |
|
376 | ## N-I dash/bash/mksh STDOUT:
|
377 | ## END
|
378 |
|
379 | #### YSH wait --verbose
|
380 | case $SH in dash|bash|mksh) exit ;; esac
|
381 |
|
382 | sleep 0.01 &
|
383 | (exit 55) &
|
384 | wait --verbose
|
385 | echo wait $?
|
386 |
|
387 | (exit 44) &
|
388 | sleep 0.01 &
|
389 | wait --all --verbose
|
390 | echo wait --all $?
|
391 |
|
392 | ## STDOUT:
|
393 | wait 0
|
394 | wait --all 1
|
395 | ## END
|
396 |
|
397 | ## N-I dash/bash/mksh STDOUT:
|
398 | ## END
|