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