OILS / test / process-table-portable.sh View on Github | oilshell.org

164 lines, 97 significant
1#!/usr/bin/env bash
2#
3# test/process-table-portable.sh: helper for process-table.sh.
4#
5# This is a portable shell script, since it has to run under dash, mksh, etc.
6#
7# Usage:
8# test/process-table-portable.sh <function name>
9
10setup() {
11 mkdir -p _tmp
12 ln -s -f -v $(which cat) _tmp/cat2
13}
14
15readonly PS_COLS='pid,ppid,pgid,sid,tpgid,comm'
16
17show_process_table() {
18 # by default, it shows processes that use the same terminal
19 #ps -o pid,ppid,pgid,sid,tname,comm | cat | _tmp/cat2
20
21 # - bash is the parent of ps, cat, ca2
22 # - the PGID is the same as bash? Oh this is for a NON-INTERACTIVE SHELL.
23 # - TPGID: controlling terminal's notion of foreground pgid?
24 # - it's always the same number, so it's misleading to associate with a process
25 # - see APUE section on setpgid(), tcsetgprp()
26
27 local sh=$1
28 local snippet=$2
29
30 case $snippet in
31 fgproc)
32 echo '[foreground process]'
33 ps -o $PS_COLS
34 ;;
35 bgproc)
36 echo '[background process]'
37 ps -o $PS_COLS &
38 wait
39 ;;
40
41 # - Gets its own PGID
42 # - Hm UNLIKE bgpipe it also gets its own TPGID? Seems consistent in all
43 # shells. Why is that?
44 fgpipe)
45 echo '[foreground pipeline, last is external]'
46 ps -o $PS_COLS | cat | _tmp/cat2
47 ;;
48
49 fgpipe-lastpipe)
50 echo '[foreground pipeline, last is builtin]'
51 ps -o $PS_COLS | _tmp/cat2 | while read -r line; do echo "$line"; done
52 ;;
53
54 bgpipe)
55 # For interactive shells, the TPGID is different here.
56 # Foreground: it matches the PGID of 'ps | cat | cat2'
57 # Background: it matches the PGID of bash!
58
59 echo '[background pipeline]'
60 ps -o $PS_COLS | cat | _tmp/cat2 &
61 wait
62 ;;
63
64 bgpipe-lastpipe)
65 echo '[background pipeline, last is builtin]'
66 ps -o $PS_COLS | _tmp/cat2 | while read -r line; do echo "$line"; done &
67 wait
68 ;;
69
70 subshell)
71 # does NOT create a new process group. So what happens when it's
72 # interrupted?
73
74 echo '[subshell]'
75 ( ps -o $PS_COLS; echo ALIVE )
76 # subshell gets its own PGID in every shell!
77 ;;
78
79 csub)
80 # does NOT create a new process group. So what happens when it's
81 # interrupted?
82 echo '[command sub]'
83 local x
84 x=$(ps -o $PS_COLS)
85 echo "$x"
86 ;;
87
88 psub)
89 case $sh in (dash|mksh)
90 return
91 esac
92
93 echo '[process sub]'
94 # use 'eval' as workaround for syntax error in dash and mksh
95 eval "cat <(ps -o $PS_COLS)"
96 # RESULTS
97 # zsh: ps and cat are in their own process groups distinct from the shell!
98 # bash: cat is in its own process group, but ps is in one with bash. Hm
99 ;;
100
101 nested_eval)
102 echo '[nested eval]'
103 ps -o $PS_COLS | tac | eval 'cat | _tmp/cat2'
104 ;;
105
106 nested_pipeline)
107 echo '[nested pipeline]'
108 ps -o $PS_COLS | { cat | _tmp/cat2; } | tac
109 ;;
110
111 nested_pipeline_last)
112 echo '[nested pipeline]'
113 ps -o $PS_COLS | tac | { cat | _tmp/cat2; }
114 ;;
115
116 *)
117 echo "Invalid snippet $snippet"
118 exit 1
119 ;;
120
121 esac
122}
123
124run_snippet() {
125 local sh=$1
126 local snippet=$2
127 local interactive=$3
128
129 echo "run_snippet $sh $snippet $interactive"
130
131 local tmp=_tmp/process-table.txt
132
133 if test $interactive = 'yes'; then
134 # Run shell with -i, but source the code first.
135
136 local more_flags=''
137 case $sh in
138 (bash|bin/osh)
139 more_flags='--rcfile /dev/null'
140 ;;
141 esac
142
143 $sh $more_flags -i -c '. $0; show_process_table "$@"' $0 $sh $snippet > $tmp
144 else
145 # Run shell without -i.
146
147 $sh $0 show_process_table $sh $snippet > $tmp
148 fi
149
150 test/process_table.py $$ $sh $snippet $interactive < $tmp
151 local status=$?
152
153 cat $tmp
154 echo
155
156 return $status
157}
158
159# We might be sourced by run_with_shell_interactive, so avoid running anything
160# in that case.
161case $1 in
162 setup|show_process_table|run_snippet)
163 "$@"
164esac