Skip to content

Commit

Permalink
util: work around macOS/FreeBSD failure on "exec 32>&2"
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Feb 23, 2024
1 parent b593819 commit 8f0dfe9
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 19 deletions.
2 changes: 1 addition & 1 deletion contrib
6 changes: 3 additions & 3 deletions lib/test-bash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ble-import lib/core-test

ble/test/start-section 'bash' 61
ble/test/start-section 'bash' 65

# case $word を quote する必要がある条件は?

Expand Down Expand Up @@ -398,7 +398,7 @@ ble/test/start-section 'bash' 61
# redirect. In bash-3.1, because of the next bug, one cannot simply close
# the file descriptor. One needs to move the file descriptor to another
# number.
if [[ -d /proc/$$/fd ]]; then
if [[ -d /proc/$$/fd ]] && { ((1)) >/dev/tty; } 2>/dev/null; then
(
exec 7>/dev/null 77>/dev/null # disable=#D0857
exec 7>/dev/tty 77>/dev/tty # disable=#D0857
Expand All @@ -417,7 +417,7 @@ ble/test/start-section 'bash' 61

# BUG bash-3.1 [Ref #D2164]
# file descriptor >= 10 cannot be closed by exec 77>&-.
if [[ -d /proc/$$/fd ]]; then
if [[ -d /proc/$$/fd ]] && { ((1)) >/dev/tty; } 2>/dev/null; then
(
exec 7>/dev/null 77>/dev/null # disable=#D0857
exec 7>&- 77>&- # disable=#D2164
Expand Down
53 changes: 53 additions & 0 deletions note.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7075,6 +7075,59 @@ bash_tips
Done (実装ログ)
-------------------------------------------------------------------------------

2024-02-23

* util: macOS で stderr が消失する問題 (reported by tessus, jon-hotaisle) [#D2165]

macOS で stderr が消滅している。というか、現象的には bash-3.1 で起きていた
現象と酷似している。

? 実は file descriptor の rediraction に失敗しているという可能性? 今まで動
いていたのは bash-3.2 用の wa である 32>&- 32>redir 等の方法がカバーして
いたから等の可能性。

調べてみると stdin の処理を実行した後に /dev/null に置き換わっている。こ
れは如何にも bash-3.2 以下で発生していたのと同じ現象である。だとすると
.nextfd が怪しい? #D2164 を確認してみると _ble_util_fd_null の初期化の時
点で置き換わると書いてあるが、現在の振る舞いは stdin の初期化までは大丈夫
である。但し、#D2164 に対する修正をした事によって状況が微妙に異なっている
だけの可能性もあるので、やはり同じ原因である可能性は高い様な気がする。

どうも発生する条件がある様だが謎である。常に起こる訳では無い。この点は
3.1 とは異なる。然し、最終的にはやはり ble/fd#is-open に於ける 2 の待避に
失敗している。exec 32>&2 ができないという事。

何か変な事が起きている。調整を行った後に fd 2 が消滅している。どういう事だ
ろう。更にそれがどうして後々に /dev/null に置き換わるのかも謎である。取り敢
えず fd が 2 に置き換わる所は確認しておきたい。

FreeBSD でも同じ現象が起こっている。minix では起こっていない。

* 因みに ble.sh のテストは全てクリアしている。

最終的に以下の bash スクリプトで問題が再現する。

#!/usr/bin/env bash
exec 51>1.txt
exec 10>&-; { exec 52<&10; } 51</dev/null; exec 51<&52
exec 50>&51
exec 50>2.txt
echo hi >&50
ls -l 1.txt 2.txt

どうやら以前通りに一旦 fd を閉じておけば失敗はしないみたいなので、常に fd
は閉じる事にする。

* ok: macOS では C.UTF-8 が効かない様だ。と思って対策しようと思ったが既に
C.UTF-8 が使われている所は皆 2>/dev/null 等がされていた。CentOS 7 の為に
同様の対策をしていてそれが未だ壊れていなかったという事。コメントで CentOS
7 に加えて macOS も言及した。

* fixed: CI で tty を使ったテストが失敗していたので、tty を開けない場合には
テストをスキップする様にする。修正した。

* fixed: そもそも test-bash のテストカウントがずれている。修正する。

2024-02-18

* util: bash-3.1 でプロンプトが表示されなくなっている [#D2164]
Expand Down
32 changes: 17 additions & 15 deletions src/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3018,20 +3018,17 @@ ble/fd#alloc/.close/.upgrade
## The file descriptor that is supposed to be modified
## @param redir
## Redirection operator plus arguments
if ((30100<=_ble_bash&&_ble_bash<40000)); then
function ble/fd#alloc/.exec {
# Note (#D0857): Bash 3.2/3.1 has a bug for the file descriptors (>= 10).
# When a file descriptor is already used, the redirections of the form
# 33>... (disable=#D0857) silently fails. To work around this bug, we
# first close the file descriptor by ble/fd#alloc/.close.
ble/fd#alloc/.close "$1"
builtin eval "exec $1$2"
}
else
function ble/fd#alloc/.exec {
builtin eval "exec $1$2"
}
fi
function ble/fd#alloc/.exec {
# Note (#D0857): Bash 3.2/3.1 has a bug for the file descriptors (>= 10).
# When a file descriptor is already used, the redirections of the form
# 33>... (disable=#D0857) silently fails. To work around this bug, we
# first close the file descriptor by ble/fd#alloc/.close.
# Note (#D2164): We also need to close the destimation file descriptor before
# performing dup2 in macOS and FreeBSD, if the destimation file descriptor
# is open and given O_CLOEXEC by ble/fd#add-cloexec, the redirection fails.
ble/fd#alloc/.close "$1"
builtin eval "exec $1$2"
}

# We now switch to the complete implementation of "ble/fd#is-open" utlizing
# "ble/fd#alloc/.nextfd", "ble/fd#alloc/.exec", and "$_ble_util_fd_null".
Expand Down Expand Up @@ -7387,7 +7384,12 @@ if ((_ble_bash>=40200)); then
# pair in systems where sizeof(wchar_t) == 2.
function ble/util/.has-bashbug-printf-uffff {
((40200<=_ble_bash&&_ble_bash<50000)) || return 1
local LC_ALL=C.UTF-8 2>/dev/null # Workaround: CentOS 7 に C.UTF-8 がなかった

# Note: CentOS 7 に C.UTF-8 がなかったので 2>/dev/null する。macOS にも
# C.UTF-8 はない。何れにしてもこれらのシステムでは sizeof(wchar_t) == 2 で
# はないので正しく UTF-8 にならなくても良い。
local LC_ALL=C.UTF-8 2>/dev/null

local ret
builtin printf -v ret '\uFFFF'
((${#ret}==2))
Expand Down

0 comments on commit 8f0dfe9

Please sign in to comment.