From 6e4bb1262eabc112933740e5de5ed05777341410 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Fri, 28 May 2021 20:03:53 +0900 Subject: [PATCH] util (ble/util/assign): work around subshell conflits --- ble.pp | 14 +++++--- lib/core-syntax.sh | 5 +-- memo/ChangeLog.md | 1 + note.txt | 37 ++++++++++++++++++++++ src/util.sh | 79 +++++++++++++++++++++++++++++++--------------- 5 files changed, 104 insertions(+), 32 deletions(-) diff --git a/ble.pp b/ble.pp index 9254b981..9d9b8c96 100644 --- a/ble.pp +++ b/ble.pp @@ -228,8 +228,10 @@ function ble/base/is-POSIXLY_CORRECT { _ble_bash_builtins_save= function ble/base/adjust-builtin-wrappers/.assign { if [[ $_ble_util_assign_base ]]; then - builtin eval -- "$1" >| "$_ble_util_assign_base.adjust-builtin" - IFS= builtin read -r -d '' defs < "$_ble_util_assign_base.adjust-builtin" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$1" >| "$_ble_local_tmpfile" + IFS= builtin read -r -d '' defs < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp else defs=$(builtin eval -- "$1") fi || ((1)) @@ -620,7 +622,7 @@ function ble/.check-environment { fi # src/util で awk を使う -function ble/bin/awk { +function ble/bin/awk/.instantiate { local path q=\' Q="'\''" if [[ $OSTYPE == solaris* ]] && type /usr/xpg4/bin/awk >/dev/null; then # Solaris の既定の awk は全然駄目なので /usr/xpg4 以下の awk を使う。 @@ -647,7 +649,11 @@ function ble/bin/awk { else return 1 fi - ble/bin/awk "$@" +} + +function ble/bin/awk { + ble/bin/awk/.instantiate && + ble/bin/awk "$@" } # Do not overwrite by .freeze-utility-path function ble/bin/.frozen:awk { :; } diff --git a/lib/core-syntax.sh b/lib/core-syntax.sh index a3af8b09..3b02799e 100644 --- a/lib/core-syntax.sh +++ b/lib/core-syntax.sh @@ -1413,11 +1413,12 @@ function ble/syntax:bash/simple-word/eval/.impl { [[ $__ble_sync_timeout ]] && __ble_sync_opts=$__ble_sync_opts:timeout=$((__ble_sync_timeout)) - local __ble_simple_word_tmpfile=$_ble_util_assign_base.$((_ble_util_assign_level++)) + local _ble_local_tmpfile; ble/util/assign/.mktmp + local __ble_simple_word_tmpfile=$_ble_local_tmpfile local __ble_script ble/util/assign __ble_script 'ble/util/conditional-sync "$__ble_sync_command" "" "$__ble_sync_weight" "$__ble_sync_opts"' &>/dev/null; local ext=$? builtin eval -- "$__ble_script" - ((_ble_util_assign_level--)) + ble/util/assign/.rmtmp else builtin eval "ble/syntax:bash/simple-word/eval/.set-result $__ble_word" &>/dev/null; local ext=$? builtin eval : # Note: bash 3.1/3.2 eval バグ対策 (#D1132) diff --git a/memo/ChangeLog.md b/memo/ChangeLog.md index 2e351200..bd0868f6 100644 --- a/memo/ChangeLog.md +++ b/memo/ChangeLog.md @@ -156,6 +156,7 @@ - tui, edit: add a new render mode for full-screen applications 817889d - main: prefer `nawk` over `mawk` and `gawk` `#D1523` `#D1524` c89aa23 - main (`ble/bin/.freeze-utility-path`): fix unupdated temporary implementations `#D1528` c70a3b4 + - util (`ble/util/assign`): work around subshell conflits `#D1578` 0000000 - test (`test-canvas`): fix dependency on `ext/contra` `#D1525` c89aa23 - util: inherit special file descriptors `#D1552` 98835b5 - global: use `_ble_term_IFS` `#D1557` d23ad3c diff --git a/note.txt b/note.txt index d383be16..c02a3eba 100644 --- a/note.txt +++ b/note.txt @@ -4663,6 +4663,43 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2021-05-29 + + * util (assign): Cygwin で assign 一時ファイルの衝突が発生している様だ [#D1578] + + assign 一時ファイルに BASHPID を付加する様にしたら特に問題は発生しない様子。 + なのでやはり assign 一時ファイルの衝突なのだろうと思われる。実際に保存され + たファイル名を観察するとやはり衝突が起こっているかも知れない。 + + 特に頻繁に起こるのは background シェルと親シェルに於ける + ble/function#getdef なのだろうという気がする。取り敢えず、ble/util/assign + におけるファイル名の確保を関数に纏める事にする。 + + 呼び出し元を出力して調べてみた所、そもそもサブシェル内部から呼び出しが発生 + しているのは ble/bin/awk の初期化のみの様であった。ble/bin/awk を、 + ble/util/assign が設定されてから即座に初期化する様に修正してみた所、 + subshell 内部からの ble/util/assign は全く発生しなくなった。 + + * 他に気になることとしてはファイルの中身が残ってしまっているという事。 + + dec する場所で一緒に clear する事も考えてみたが、実際に実装を見てみると一 + 時ファイルの中身を呼び出す前に dec している。読み出し中にエラーがあって中 + 断した時の事を考えてだろうか。然し、実行が中断してしまう程のエラーが起こ + る状況が分からない。set -ue は off にしているし failglob は起こりようがな + い。なので、dec の位置を変更して dec と一緒にファイルのクリアも行う様にす + るというのは一つの手である。 + + 特に大量のデータがある場合にはやはりファイルの中身をクリアするのが望まし + い。これで多少パフォーマンスが落ちてしまうかもしれないが、問題になりそう + なのは初期化ぐらいの物であって、初期化の場合には色々他にも bottleneck が + あるだろうという事で余り気にしない事にする。いざ初期化時間を縮めようと思っ + たらまた何か別の初期化を遅延させる事にするのが良い。何れにしてもプロファ + イリングした上で決める事である。 + + 取り敢えず今の所はファイルの中身は消去する事にする。 + + 対策は取り敢えずそれでよしという事にする。 + 2021-05-28 * ble-reload した時に alias が無効になってしまう [#D1577] diff --git a/src/util.sh b/src/util.sh index 21a4e331..25982ecb 100644 --- a/src/util.sh +++ b/src/util.sh @@ -2329,26 +2329,50 @@ function ble/util/readarray { ## @param[in] command... ## 実行するコマンドを指定します。 ## -_ble_util_assign_base=$_ble_base_run/$$.ble_util_assign.tmp + +_ble_util_assign_base=$_ble_base_run/$$.util.assign.tmp _ble_util_assign_level=0 +if ((_ble_bash>=40000)); then + function ble/util/assign/.mktmp { + _ble_local_tmpfile=$_ble_util_assign_base.$((_ble_util_assign_level++)) + ((BASH_SUBSHELL)) && _ble_local_tmpfile=$_ble_local_tmpfile.$BASHPID + } +else + function ble/util/assign/.mktmp { + _ble_local_tmpfile=$_ble_util_assign_base.$((_ble_util_assign_level++)) + ((BASH_SUBSHELL)) && _ble_local_tmpfile=$_ble_local_tmpfile.$RANDOM + } +fi +function ble/util/assign/.rmtmp { + ((_ble_util_assign_level--)) +#%if !release + if ((BASH_SUBSHELL)); then + printf 'caller %s\n' "${FUNCNAME[@]}" >| "$_ble_local_tmpfile" + else + : >| "$_ble_local_tmpfile" + fi +#%else + : >| "$_ble_local_tmpfile" +#%end +} if ((_ble_bash>=40000)); then # mapfile の方が read より高速 function ble/util/assign { - local _ble_local_tmp=$_ble_util_assign_base.$((_ble_util_assign_level++)) - builtin eval -- "$2" >| "$_ble_local_tmp" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? _ble_local_arr= - ((_ble_util_assign_level--)) - mapfile -t _ble_local_arr < "$_ble_local_tmp" + mapfile -t _ble_local_arr < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp IFS=$'\n' builtin eval "$1=\"\${_ble_local_arr[*]}\"" return "$_ble_local_ret" } else function ble/util/assign { - local _ble_local_tmp=$_ble_util_assign_base.$((_ble_util_assign_level++)) - builtin eval -- "$2" >| "$_ble_local_tmp" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? - ((_ble_util_assign_level--)) - TMOUT= IFS= builtin read -r -d '' "$1" < "$_ble_local_tmp" + TMOUT= IFS= builtin read -r -d '' "$1" < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp builtin eval "$1=\${$1%$'\n'}" return "$_ble_local_ret" } @@ -2366,41 +2390,41 @@ fi ## if ((_ble_bash>=40000)); then function ble/util/assign-array { - local _ble_local_tmp=$_ble_util_assign_base.$((_ble_util_assign_level++)) - builtin eval -- "$2" >| "$_ble_local_tmp" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? - ((_ble_util_assign_level--)) - mapfile -t "$1" < "$_ble_local_tmp" + mapfile -t "$1" < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp return "$_ble_local_ret" } else function ble/util/assign-array { - local _ble_local_tmp=$_ble_util_assign_base.$((_ble_util_assign_level++)) - builtin eval -- "$2" >| "$_ble_local_tmp" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? - ((_ble_util_assign_level--)) - ble/util/mapfile "$1" < "$_ble_local_tmp" + ble/util/mapfile "$1" < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp return "$_ble_local_ret" } fi if ! ((_ble_bash>=40400)); then function ble/util/assign-array0 { - local _ble_local_tmp=$_ble_util_assign_base.$((_ble_util_assign_level++)) - builtin eval -- "$2" >| "$_ble_local_tmp" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? - ((_ble_util_assign_level--)) - mapfile -d '' -t "$1" < "$_ble_local_tmp" + mapfile -d '' -t "$1" < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp return "$_ble_local_ret" } else function ble/util/assign-array0 { - local _ble_local_tmp=$_ble_util_assign_base.$((_ble_util_assign_level++)) - builtin eval -- "$2" >| "$_ble_local_tmp" + local _ble_local_tmpfile; ble/util/assign/.mktmp + builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? - ((_ble_util_assign_level--)) local IFS= i=0 _ble_local_arr - while builtin read -r -d '' "_ble_local_arr[i++]"; do :; done < "$_ble_local_tmp" + while builtin read -r -d '' "_ble_local_arr[i++]"; do :; done < "$_ble_local_tmpfile" + ble/util/assign/.rmtmp [[ ${_ble_local_arr[--i]} ]] || builtin unset -v "_ble_local_arr[i]" ble/util/unlocal i IFS builtin eval "$1=(\"\${_ble_local_arr[@]}\")" @@ -2408,6 +2432,9 @@ else } fi +# ble/bin/awk の初期化に ble/util/assign を使うので +ble/bin/awk/.instantiate + # # functions # @@ -3195,7 +3222,7 @@ function ble/util/msleep/.use-read-timeout { # tmpfile case $file in (fifo) - _ble_util_msleep_tmp=$_ble_base_run/$$.ble_util_msleep.pipe + _ble_util_msleep_tmp=$_ble_base_run/$$.util.msleep.pipe if [[ ! -p $_ble_util_msleep_tmp ]]; then [[ -e $_ble_util_msleep_tmp ]] && ble/bin/rm -rf "$_ble_util_msleep_tmp" ble/bin/mkfifo "$_ble_util_msleep_tmp"