OILS / demo / 03-background-status.sh View on Github | oils.pub

227 lines, 143 significant
1#!/usr/bin/env bash
2#
3# Usage:
4# demo/background-status.sh <function name>
5
6set -o nounset
7#set -o pipefail
8#set -o errexit # wait waill fail with this
9
10do_some_work() {
11 sleep 0.2
12 exit $1
13}
14
15wait_pids() {
16 { sleep 0.1; exit 5; } &
17 pid1=$!
18
19 do_some_work 6 &
20 pid2=$!
21
22 { sleep 0.3; exit 7; } &
23 pid3=$!
24
25 do_some_work 8 &
26 pid4=$!
27
28 echo "Waiting for PIDs $pid1 $pid2 $pid3"
29
30 wait $pid1; echo $?
31 wait $pid2; echo $?
32 wait $pid3; echo $?
33 wait $pid4; echo $?
34
35 echo 'Done'
36}
37
38# NOTE: dash/mksh/zsh all lack the -n option. That seems like an oversight.
39wait_next() {
40 { sleep 0.1; exit 8; } &
41 pid1=$!
42
43 { sleep 0.2; exit 9; } &
44 pid2=$!
45
46 { sleep 0.3; exit 10; } &
47 pid3=$!
48
49 wait -n; echo $?
50 wait -n; echo $?
51 wait -n; echo $?
52
53 echo 'Done'
54}
55
56both() {
57 wait_pids
58 wait_next
59}
60
61# ERROR: says "no job control"
62job_control() {
63 { sleep 0.1; exit 8; } &
64 fg
65}
66
67# ERROR: says "no job control"
68job_control2() {
69 { sleep 0.1; exit 8; } &
70 %1
71}
72
73jobs_list() {
74 local start_what=${1:-process} # or pipeline
75 local wait_style=${2:-all}
76
77 # Works with: dash/ash, bash mksh yash
78 # Does NOT work with zsh
79 #
80 # OSH:
81 # - jobs list looks weird
82 # - extra stuff on stderr
83 # but otherwise it works
84
85 pids_down=''
86 pids_up=''
87 for i in 3 2 1; do
88 case $start_what in
89 process)
90 { sleep $i; echo i=$i; exit $i; } &
91 pid=$!
92 ;;
93 pipeline)
94 sleep $i | echo i=$i | ( exit $i ) &
95 pid=$!
96 ;;
97 *)
98 echo "Invalid arg '$start_what'" >&2
99 return 1
100 ;;
101 esac
102
103 pids_down="$pids_down $pid"
104 pids_up="$pid $pids_up"
105 echo "--- started $i"
106 jobs -l
107 echo
108
109 done
110 echo $pids_down
111 echo $pids_up
112
113 pid_list=''
114 case $wait_style in
115 pass_all)
116 wait $pids_down
117 ;;
118 all)
119 wait
120 ;;
121 next)
122 for i in $pids_down; do
123 wait -n
124 echo "--- wait -n --> status=$?"
125 done
126 ;;
127 down_one)
128 pid_list=$pids_down
129 ;;
130 up_one)
131 pid_list=$pids_up
132 ;;
133 down_jobs)
134 pid_list='%3 %2 %1'
135 ;;
136 up_jobs)
137 pid_list='%1 %2 %3'
138 ;;
139 none)
140 echo 'Not waiting'
141
142 # When can we remove the (pid -> status) mapping?
143 # If we don't wait, We never do. The shell exists, and the processes
144 # keep going!
145 # So the actual 'wait' command is the thing that removes records, NOT
146 # process death.
147
148 # Some dummy processes
149 for i in 1 2 3; do
150 sleep 0.01
151 done
152 ;;
153 *)
154 echo "Invalid wait style '$wait_style'" >& 2
155 wait
156 return 1
157 esac
158
159 case $wait_style in
160 down_*|up_*)
161 for p in $pid_list; do
162 wait $p
163 echo "--- pid $p --> status $?"
164
165 # Hm dash/ash, and yash have a SIMILAR bug as OSH - status can be 127,
166 # but only jobs -l
167 #
168 # bash and mksh do it correctly
169 # zsh is messed up in other ways
170 #
171 # So this means that our way of handling failure only works in BASH/mksh,
172 # not in POSIX shell! There are similar problems with xargs. Need a
173 # blog post about this.
174 jobs -l # problem: this can "lose" exit codes
175 done
176 ;;
177 esac
178
179 echo '--- Jobs after waiting'
180 jobs -l
181 echo '---'
182
183 # the status is the last one, which is 2
184 echo status=$?
185}
186
187stopped_process() {
188 sleep 5 &
189 local pid=$!
190
191 set -x
192 sleep 0.1
193 kill -STOP $pid
194
195 #kill -TERM $pid
196
197 # wait is only for exiting
198 wait $pid
199 echo status=$?
200}
201
202# from test/process-table-portable.sh
203readonly PS_COLS='pid,ppid,pgid,sid,tpgid,comm'
204
205last_id() {
206 sleep 1 | cat &
207
208 # But what's the progress group leader?
209 #
210 # In non-interactive shell, it's the shell itself
211 # In an interactive shell, it's the FIRST part of the pipeline.
212 #
213 # This is super confusing.
214 # So when you do wait $! on the LAST part of the pipeline, are you waiting on
215 # an individual process, or a JOB that's the pipeline. Gah
216 ps -o $PS_COLS
217
218 # 6277 is the last part of the pipeline! You can 'wait' on it?
219 pid=$!
220 jobs -l
221 echo pid=$pid
222 set -x
223 wait $pid
224
225}
226
227"$@"