1 | #!/usr/bin/env bash
|
2 | #
|
3 | # See what system calls shells make for various constructs. Similar to
|
4 | # test/syscall.sh.
|
5 | #
|
6 | # Usage:
|
7 | # demo/compare-strace.sh <function name>
|
8 |
|
9 | set -o nounset
|
10 | set -o pipefail
|
11 | set -o errexit
|
12 |
|
13 | banner() {
|
14 | echo
|
15 | echo
|
16 | echo -e -n "\t"; echo "$@"
|
17 | echo
|
18 | echo
|
19 | }
|
20 |
|
21 | redir-strace() {
|
22 | ### trace relevant calls
|
23 |
|
24 | strace -e open,fcntl,dup2,close -- "$@"
|
25 | }
|
26 |
|
27 | redir() {
|
28 | #for sh in dash bash mksh bin/osh; do
|
29 |
|
30 | # hm bin/osh and zsh have too many close() calls. I think this is the Python
|
31 | # interpreter
|
32 | for sh in dash bash mksh; do
|
33 |
|
34 | banner "$sh"
|
35 |
|
36 | #local code='exec 3>_tmp/3.txt; echo hello >&3; exec 3>&-; cat _tmp/3.txt'
|
37 |
|
38 | #local code='exec 4>_tmp/4.txt; echo hello >&4; exec 4>&-; cat _tmp/4.txt'
|
39 | #local code='true 2>&1'
|
40 |
|
41 | local code='true > _tmp/out.txt'
|
42 | redir-strace $sh -c "$code"
|
43 | done
|
44 | }
|
45 |
|
46 | io-strace() {
|
47 | ### trace relevant calls
|
48 |
|
49 | # -ff because it's a pipeline
|
50 | strace -ff -e 'open,close,fcntl,read,write' -- "$@"
|
51 | }
|
52 |
|
53 | readonly OSH_NATIVE=_bin/cxx-dbg/osh
|
54 |
|
55 | readonly READ_SH='
|
56 | { echo "0123456789"; echo "ABCDEFGHIJ"; } |
|
57 | while read -r line; do echo $line; done
|
58 | '
|
59 |
|
60 | read-builtin() {
|
61 | # RESULTS
|
62 | #
|
63 | # All shells read 1 byte at a time
|
64 |
|
65 | for sh in dash bash $OSH_NATIVE; do
|
66 | banner "$sh"
|
67 |
|
68 | io-strace $sh -c "$READ_SH"
|
69 | done
|
70 | }
|
71 |
|
72 | read-lines-from-disk-file() {
|
73 | # dash can't read this script
|
74 |
|
75 | # RESULTS:
|
76 | # mksh: reads 512 bytes at a time
|
77 | # bash: 80 and then 2620?
|
78 | # osh_native: using libc readline, it's 832 bytes at a time.
|
79 |
|
80 | # I think we can have a "regular file reader", which is different than a pipe
|
81 | # reader?
|
82 |
|
83 | for sh in mksh bash $OSH_NATIVE; do
|
84 | banner "$sh"
|
85 |
|
86 | # Run without args
|
87 | io-strace $sh $0
|
88 | done
|
89 | }
|
90 |
|
91 | read-lines-from-pipe() {
|
92 | # RESULTS:
|
93 | # - dash does read(8192), hm
|
94 | # - mksh reads 1 byte at a time
|
95 | # - bash reads 1 byte at a time
|
96 | # - zsh reads 1 byte at a time
|
97 | # - osh_native with libc does 832 bytes at time.
|
98 |
|
99 | for sh in dash mksh bash zsh $OSH_NATIVE; do
|
100 | banner "$sh"
|
101 |
|
102 | # Run without args
|
103 | io-strace sh -c "cat testdata/osh-runtime/hello_world.sh | $sh"
|
104 | done
|
105 | }
|
106 |
|
107 | job-control-trace() {
|
108 | ### trace relevant calls
|
109 |
|
110 | # why isn't tcsetpgrp valid?
|
111 | strace -ff -e fork,execve,setpgid -- "$@"
|
112 | }
|
113 |
|
114 | job-control() {
|
115 | #for sh in dash bash mksh bin/osh; do
|
116 |
|
117 | # hm bin/osh and zsh have too many close() calls. I think this is the Python
|
118 | # interpreter
|
119 | for sh in dash bash mksh zsh; do
|
120 |
|
121 | echo
|
122 | echo "--- $sh ---"
|
123 | echo
|
124 |
|
125 | local code='ls | wc -l'
|
126 | job-control-trace $sh -i -c "$code"
|
127 | done
|
128 | }
|
129 |
|
130 | interactive() {
|
131 | local sh=dash
|
132 | local code='ls | wc -l'
|
133 |
|
134 | # is tcsetpgrp() an ioctl? It takes a file descriptor. I see setpgid() but
|
135 | # not tcsetpgrp().
|
136 |
|
137 | strace -c $sh -c "$code"
|
138 | echo -----
|
139 | strace -c $sh -i -c "$code"
|
140 | }
|
141 |
|
142 | #
|
143 | # Translation tests
|
144 | #
|
145 |
|
146 | readonly BASE_DIR=_tmp/strace
|
147 |
|
148 | _compare-native() {
|
149 | local code=$1
|
150 |
|
151 | rm -r -f -v $BASE_DIR
|
152 | mkdir -p $BASE_DIR
|
153 |
|
154 | ninja $OSH_NATIVE
|
155 |
|
156 | strace -ff -o $BASE_DIR/py -- bin/osh -c "$code"
|
157 | strace -ff -o $BASE_DIR/cpp -- $OSH_NATIVE -c "$code"
|
158 |
|
159 | wc -l $BASE_DIR/*
|
160 | }
|
161 |
|
162 | native-command-sub() {
|
163 | _compare-native 'echo $(echo hi)'
|
164 | }
|
165 |
|
166 | native-redirect() {
|
167 | _compare-native 'echo hi > _tmp/redir'
|
168 | }
|
169 |
|
170 | native-read-builtin() {
|
171 | _compare-native "$READ_SH"
|
172 | }
|
173 |
|
174 | if test $# -eq 0; then
|
175 | echo "$0: expected arguments"
|
176 | else
|
177 | "$@"
|
178 | fi
|