1 | ---
|
2 | default_highlighter: oils-sh
|
3 | ---
|
4 |
|
5 | OSH Quirks
|
6 | ==========
|
7 |
|
8 | This document describes corner cases in OSH.
|
9 |
|
10 | Related: [Known Differences](known-differences.html).
|
11 |
|
12 | <div id="toc">
|
13 | </div>
|
14 |
|
15 | ## For Bash Compatibility
|
16 |
|
17 | ### The meaning of `()` on the RHS
|
18 |
|
19 | In Oils, **values** are tagged with types like `Str` and `AssocArray`, as
|
20 | opposed to the *locations* of values (cells).
|
21 |
|
22 | This statement binds an empty indexed array to the name `x`:
|
23 |
|
24 | x=() # indexed by integers
|
25 |
|
26 | **Quirk**: When it's clear from the context, `()` means an empty
|
27 | **associative** array:
|
28 |
|
29 | declare -A x=() # indexed by strings, because of -A
|
30 |
|
31 | This only applies when the array is empty. Otherwise the type is determined by
|
32 | the literal:
|
33 |
|
34 | declare x=(one two) # indexed array
|
35 | declare x=(['k']=v) # associative array
|
36 |
|
37 | Redundant but OK:
|
38 |
|
39 | declare -a x=(one two) # indexed array
|
40 | declare -A x=(['k']=v) # associative array
|
41 |
|
42 | Errors:
|
43 |
|
44 | declare -A x=(one two) # inconsistent
|
45 | declare -a x=(['k']=v) # inconsistent
|
46 |
|
47 | ## Interactive Shell
|
48 |
|
49 | ### With job control, the DEBUG trap is disabled for the last part of a pipeline
|
50 |
|
51 | First, some background. These two shell features are fundamentally
|
52 | incompatible:
|
53 |
|
54 | - Job control: e.g. putting a pipeline in a process group, so it can be
|
55 | suspended and cancelled all at once.
|
56 | - `shopt -s lastpipe` semantics: the last part of a pipeline can (sometimes) be
|
57 | run in the current shell.
|
58 | - [OSH]($xref) uses it by default because it makes `echo hi | read myvar` work. So
|
59 | [OSH]($xref) is like [zsh]($xref), but unlike [bash](xref).
|
60 |
|
61 | As evidence of this incompatibility, note that:
|
62 |
|
63 | - [bash]($xref) simply ignores the `shopt -s lastpipe` setting in job control
|
64 | shells
|
65 | - [zsh]($xref) doesn't allow you to suspend some pipelines
|
66 |
|
67 | ---
|
68 |
|
69 | Now that we have that background, note that there's is a **third** feature that
|
70 | interacts: the `DEBUG` trap.
|
71 |
|
72 | [OSH]($xref) emulates the [bash]($xref) `DEBUG` trap, which runs before "leaf"
|
73 | commands like `echo hi`, `a=b`, etc.
|
74 |
|
75 | If we run this trap before the last part of a pipeline, **and** that part is
|
76 | run in the current shell (`lastpipe`), then the DEBUG trap makes an existing
|
77 | race condition worse.
|
78 |
|
79 | For example, in
|
80 |
|
81 | echo hi | cat
|
82 |
|
83 | there's nothing stopping `echo hi` from finishing before `cat` is even started,
|
84 | which means that `cat` can't join the process group of the leader.
|
85 |
|
86 | So we simply disable the `DEBUG` trap for the last part of the pipeline, but
|
87 | **only** when job control is enabled. This won't affect debugging batch
|
88 | programs.
|
89 |
|
90 | Related issues in other shells:
|
91 |
|
92 | - bash: <https://superuser.com/questions/1084406/chained-pipes-in-bash-throws-operation-not-permitted>
|
93 | - fish: <https://github.com/fish-shell/fish-shell/issues/7474>
|
94 |
|
95 |
|
96 | <!--
|
97 |
|
98 | ### errexit message and optimized subshells
|
99 |
|
100 | For all shells:
|
101 |
|
102 | sh -c 'date'
|
103 |
|
104 | gets rewritten into:
|
105 |
|
106 | sh -c 'exec date'
|
107 |
|
108 | That is, they **reuse the parent process**.
|
109 |
|
110 | Most shells don't print any diagnostic info when `errexit` is on. However, YSH
|
111 | does:
|
112 |
|
113 | osh -o errexit -c 'false'
|
114 | [ -c flag ]:1: fatal: Exiting with status 1
|
115 |
|
116 | `false` is a builtin rather than an external process, so YSH can print that
|
117 | message. But when running an external process, the message is lost:
|
118 |
|
119 | osh -o errexit -c 'env false'
|
120 | (silently fails with code 1)
|
121 | -->
|
122 |
|
123 | ## Related
|
124 |
|
125 | - The doc on [warts](warts.html) relates to YSH.
|
126 |
|