1 #!/usr/bin/env bash
2 #
3 # Job control constructs:
4 # & terminator (instead of ;)
5 # $! -- last PID
6 # wait builtin (wait -n waits for next)
7 #
8 # Only interactive:
9 # fg
10 # bg
11 # %1 -- current job
12
13 #### wait with nothing to wait for
14 wait
15 ## status: 0
16
17 #### wait -n with nothing to wait for
18 # The 127 is STILL overloaded. Copying bash for now.
19 wait -n
20 ## status: 127
21 ## OK dash status: 2
22 ## OK mksh status: 1
23
24 #### wait with jobspec syntax %nonexistent
25 wait %nonexistent
26 ## status: 127
27 ## OK dash status: 2
28
29 #### wait with invalid PID
30 wait 12345678
31 ## status: 127
32
33 #### wait with invalid arg
34 wait zzz
35 ## status: 2
36 ## OK bash status: 1
37 # mksh confuses a syntax error with 'command not found'!
38 ## BUG mksh status: 127
39
40 #### Builtin in background
41 echo async &
42 wait
43 ## stdout: async
44
45 #### External command in background
46 sleep 0.01 &
47 wait
48 ## stdout-json: ""
49
50 #### Pipeline in Background
51 echo hi | { exit 99; } &
52 wait $!
53 echo status=$?
54 ## stdout: status=99
55
56 #### Wait for job doesn't support PIPESTATUS
57
58 # foreground works
59 { echo hi; exit 55; } | { exit 99; }
60 echo pipestatus=${PIPESTATUS[@]}
61
62 # background doesn't work
63 { echo hi; exit 55; } | { exit 99; } &
64 wait %+
65 echo pipestatus=${PIPESTATUS[@]}
66 ## STDOUT:
67 pipestatus=55 99
68 pipestatus=99
69 ##
70 ## N-I dash status: 2
71 ## N-I dash stdout-json: ""
72
73 #### Brace group in background, wait all
74 { sleep 0.09; exit 9; } &
75 { sleep 0.07; exit 7; } &
76 wait # wait for all gives 0
77 echo "status=$?"
78 ## stdout: status=0
79
80 #### Wait on background process PID
81 { sleep 0.09; exit 9; } &
82 pid1=$!
83 { sleep 0.07; exit 7; } &
84 pid2=$!
85 wait $pid1
86 echo "status=$?"
87 wait $pid2
88 echo "status=$?"
89 ## stdout-json: "status=9\nstatus=7\n"
90
91 #### Wait on multiple specific IDs returns last status
92 { sleep 0.08; exit 8; } &
93 jid1=$!
94 { sleep 0.09; exit 9; } &
95 jid2=$!
96 { sleep 0.07; exit 7; } &
97 jid3=$!
98 wait $jid1 $jid2 $jid3 # NOTE: not using %1 %2 %3 syntax on purpose
99 echo "status=$?" # third job I think
100 ## stdout: status=7
101
102 #### wait -n
103 { sleep 0.09; exit 9; } &
104 { sleep 0.03; exit 3; } &
105 wait -n
106 echo "status=$?"
107 wait -n
108 echo "status=$?"
109 ## stdout-json: "status=3\nstatus=9\n"
110 ## N-I dash stdout-json: "status=2\nstatus=2\n"
111 ## N-I mksh stdout-json: "status=1\nstatus=1\n"
112
113 #### Async for loop
114 for i in 1 2 3; do
115 echo $i
116 sleep 0.0$i
117 done &
118 wait
119 ## stdout-json: "1\n2\n3\n"
120 ## status: 0
121
122 #### Background process doesn't affect parent
123 echo ${foo=1}
124 echo $foo
125 echo ${bar=2} &
126 wait
127 echo $bar # bar is NOT SET in the parent process
128 ## stdout-json: "1\n1\n2\n\n"
129
130 #### Background process and then a singleton pipeline
131
132 # This was inspired by #416, although that symptom there was timing, so it's
133 # technically not a regression test. It's hard to test timing.
134
135 { sleep 0.1; exit 42; } &
136 echo begin
137 ! true
138 echo end
139 wait $!
140 echo status=$?
141 ## STDOUT:
142 begin
143 end
144 status=42
145 ## END