| 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 |
|