Skip to content

Commit

Permalink
edit: work around the wrong job information of Bash in trap handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Dec 20, 2020
1 parent d82535e commit bc4735e
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 15 deletions.
4 changes: 4 additions & 0 deletions make_command.sh
Expand Up @@ -319,6 +319,10 @@ function sub:scan {
sub:scan/memo-numbering
}

function sub:show-contrib-in-changelog {
sed -n 's/.*([^()]* by \([^()]*\)).*/\1/p' ChangeLog.md | sort | uniq -c | sort -rn
}

#------------------------------------------------------------------------------
# sub:release-note
#
Expand Down
7 changes: 4 additions & 3 deletions memo/ChangeLog.md
Expand Up @@ -5,18 +5,19 @@

## New features

- complete/mandb: support mandb in FreeBSD `#D1432` 0000000
- complete/mandb: support mandb in FreeBSD `#D1432` 6c54f79

## Changes

- syntax: exclude <code>\\ + LF</code> at the word beginning from words (motivated by cmplstofB) `#D1431` 67e62d6
- complete: do not quote `:` and `=` in non-filename completions generated by progcomp `#D1434` 0000000
- complete: do not quote `:` and `=` in non-filename completions generated by progcomp (reported by 3ximus) `#D1434` d82535e

## Fixes

- term: fix a bug that VTE based terminals are not recognized `#D1427` 7e16d9d
- complete: fix a problem that candidates are not updated after menu-filter (reported by 3ximus) `#D1428` 98fbc1c
- complete/mandb: fix BS contamination used by nroff to represent bold `#D1429` 0000000
- complete/mandb: fix BS contamination used by nroff to represent bold (reported by rlnore) `#D1429` b5c875a
- edit: work around the wrong job information of Bash in trap handlers (reported by 3ximus) `#D1435` 0000000

## Internal changes and fixes

Expand Down
63 changes: 63 additions & 0 deletions memo/D1435.bashrc
@@ -0,0 +1,63 @@

# source 3ximus.dotfiles/.bash/git-prompt.sh
# source 3ximus.dotfiles/.bash/prompts/prompt_7.sh
# source ~/.mwg/src/ble.sh/out/ble.sh
#------------------------------------------------------------------------------
# source 3ximus.dotfiles/.bash/git-prompt.sh
# GIT_PS1_SHOWDIRTYSTATE='nonempty'
# GIT_PS1_SHOWSTASHSTATE='nonempty'
# GIT_PS1_SHOWUNTRACKEDFILES='nonempty'
# PROMPT_COMMAND='__git_ps1 "" "\\$ " " %s"'
# source ~/.mwg/src/ble.sh/out/ble.sh
#------------------------------------------------------------------------------
# PROMPT_COMMAND='(true)'
# source ~/.mwg/src/ble.sh/out/ble.sh
#------------------------------------------------------------------------------
# PROMPT_COMMAND='(date;printf "%s\n" "${FUNCNAME[*]}")>>a.txt'
# source ~/.mwg/src/ble.sh/out/ble.sh

# Result:
#
# ble/prompt/update/.eval-prompt_command.1
# ble/prompt/update/.eval-prompt_command
# ble/prompt/update ble/textarea#render
# ble/textarea#redraw
# ble-edit/attach/TRAPWINCH
# blehook/invoke
# ble/builtin/trap/.handler
#------------------------------------------------------------------------------
# PROMPT_COMMAND='pcmd'
# pcmd() {
# echo "QQQ:${FUNCNAME[*]: -1}"
# jobs
# echo MMM
# (true)
# jobs # ここで (true) が終了ジョブとして表示される。
# echo ZZZ
# } >> a.txt
# source ~/.mwg/src/ble.sh/out/ble.sh

# trapwinch() {
# (true); jobs
# }
#trap '(true); jobs' WINCH
#------------------------------------------------------------------------------

#trap '(true); jobs' WINCH
#trap '(true); jobs' INT


# trapwinch() {
# (true)
# echo abc
# (jobs -- "(")
# echo def
# jobs
# }
# trap trapwinch WINCH

#------------------------------------------------------------------------------

# trap '(true)' WINCH
# bind -x '"\C-u":true'
# bind -x '"\C-t":jobs'
129 changes: 129 additions & 0 deletions memo/D1435.spike1.patch
@@ -0,0 +1,129 @@
From 0bcc167a48f4052db23dcb0111b640e46a24a317 Mon Sep 17 00:00:00 2001
From: Koichi Murase <myoga.murase@gmail.com>
Date: Sun, 20 Dec 2020 13:18:21 +0900
Subject: [PATCH] D1435 spike1

---
lib/core-syntax.sh | 9 +++++++++
src/edit.sh | 9 +++++++--
src/util.sh | 34 +++++++++++++++++++++++++++++++++-
3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/lib/core-syntax.sh b/lib/core-syntax.sh
index bcdffa8..fce7f13 100644
--- a/lib/core-syntax.sh
+++ b/lib/core-syntax.sh
@@ -5897,6 +5897,15 @@ function ble/syntax/highlight/cmdtype1 {
# #D1341 #D1355 locale 対策
function ble/syntax/highlight/cmdtype/.jobs { local LC_ALL=C; jobs; } 2>/dev/null
function ble/syntax/highlight/cmdtype/.is-job-name {
+ # #D1435 trap handler の中で動作している時には jobs はサブシェルの中で実行す
+ # る。jobs を直接実行する為にはジョブ変化の情報を失わない為に、直前に
+ # joblist.check でジョブ情報を読んでおかなければならないが、trap handler の中
+ # だと変なジョブ情報が混入してしまう。
+ if [[ $ble_builtin_trap_processing ]] && ! ble/util/is-running-in-subshell; then
+ (ble/syntax/highlight/cmdtype/.is-job-name)
+ return "$?"
+ fi
+
ble/util/joblist.check

local value=$1 word=$2
diff --git a/src/edit.sh b/src/edit.sh
index ad05923..06f5450 100644
--- a/src/edit.sh
+++ b/src/edit.sh
@@ -4413,7 +4413,7 @@ function ble/builtin/exit {
((${#opt_args[@]})) || ble/array#push opt_args "$ext"

local joblist
- ble/util/joblist
+ ble/util/joblist force
if ((${#joblist[@]})); then
local ret
while
@@ -4427,6 +4427,11 @@ function ble/builtin/exit {
fi
[[ $cancel_reason ]]
do
+ # #D1435: trap handler の中だったとしてもサブシェルの中ではなくて直接
+ # jobs を実行する。何れにしても情報を出力するので、ユーザの目には変なジョ
+ # ブが混入するのを防げない。サブシェルの中で実行すると、いつまでも変なジョ
+ # ブ情報が消えず蓄積するので、此処では敢えて trap handler の中でも直接
+ # jobs を実行する。
jobs
ble/builtin/read -ep "\e[38;5;12m[ble: There are $cancel_reason]\e[m Leave the shell anyway? [yes/No] " ret
case $ret in
@@ -7451,7 +7456,7 @@ function ble/widget/command-help/.type {
fi

if [[ $type == keyword && $command != "$literal" ]]; then
- if [[ $command == %* ]] && jobs -- "$command" &>/dev/null; then
+ if [[ $command == %* ]] && ble/util/joblist/is-job "$command"; then
type=jobs
else
# type -a の第二候補を用いる #D1406
diff --git a/src/util.sh b/src/util.sh
index 91bed57..3641561 100644
--- a/src/util.sh
+++ b/src/util.sh
@@ -1519,6 +1519,7 @@ function ble/builtin/trap/.handler {
local _ble_trap_ext=$? _ble_trap_sig=$1 _ble_trap_name=$2

# ble.sh hook
+ local ble_builtin_trap_processing=1
ble/util/setexit "$_ble_trap_ext"
blehook/invoke "$_ble_trap_name"

@@ -2694,9 +2695,31 @@ function ble/urange#shift {
}

#------------------------------------------------------------------------------
-## 関数 ble/util/joblist
+
+## 関数 ble/util/joblist/is-job name
+## 指定した文字列が jobs によって認識されるジョブ名かどうかを判定します。
+function ble/util/joblist/is-job {
+ if [[ $ble_builtin_trap_processing ]]; then
+ # #D1435 変なジョブ情報が混入するので trap handler の中では
+ # ジョブ情報は更新しない。サブシェルの中で判定を行う。
+ (jobs -- "$1")
+ else
+ # ジョブ情報が失われない様に先にジョブ情報を確認してから判定を行う。
+ ble/util/joblist.check
+ jobs -- "$1"
+ fi
+} &>/dev/null
+
+## 関数 ble/util/joblist opts
## 現在のジョブ一覧を取得すると共に、ジョブ状態の変化を調べる。
##
+## @var[in] opts
+## force trap handler の中でもジョブ情報更新を強制する。
+## trap handler の中だと変なジョブ情報を拾うので、
+## 通常は trap handler の中ではジョブ一覧は更新しない (#D1435)。
+## 然し、exit 等明示的に現在のジョブをチェックする必要がある所では
+## 現在のジョブの確認を強制する必要がある。
+##
## @var[in,out] _ble_util_joblist_events
## @var[out] joblist ジョブ一覧を格納する配列
## @var[in,out] _ble_util_joblist_jobs 内部使用
@@ -2712,6 +2735,15 @@ _ble_util_joblist_jobs=
_ble_util_joblist_list=()
_ble_util_joblist_events=()
function ble/util/joblist {
+ local opts
+ # #D1435 trap handler の中で jobs を実行すると変なジョブも拾ってしまうので、
+ # trap handler の中では joblist の更新は実行しない事にする。単に前回の結果を
+ # そのまま返して終了する。
+ if [[ $ble_builtin_trap_processing && :$opts: != *:force:* ]]; then
+ joblist=("${_ble_util_joblist_list[@]}")
+ return 0
+ fi
+
local jobs0
ble/util/assign jobs0 'jobs'
if [[ $jobs0 == "$_ble_util_joblist_jobs" ]]; then
--
2.21.3

112 changes: 110 additions & 2 deletions note.txt
Expand Up @@ -1197,6 +1197,12 @@ bash_tips
ToDo
-------------------------------------------------------------------------------

2020-12-19

* Note (#D1435): blehook WINCH を処理している最中に終了したユーザのジョブがあ
るとその通知が画面に表示されない可能性がある。これは実際に起こりうるのかど
うか確認していない。

2020-12-14

* progcomp: progcomp で生成された補完候補を現在 quote している。
Expand Down Expand Up @@ -3709,9 +3715,111 @@ bash_tips
Done (実装ログ)
-------------------------------------------------------------------------------

2020-12-20

* edit: WINCH 後に偽のジョブ情報が表示される (reported by 3ximus) [#D1435]
https://github.com/akinomyoga/ble.sh/issues/78

前回報告を受けていた謎のジョブ終了メッセージについて。
これは端末のサイズを変えた直後に起こるという新情報を得た。
3ximus/dotfiles の .bashrc を確認して再現を試みた所、
git-prompt.sh, prompt_7.sh, ble.sh の組み合わせで再現できた。

更に設定を最小化していく。どうやら fork があると
jobs にメッセージが乗る様になってしまうらしい。

これの回避方法としてどの様な方法があるか。

a jobs で得た新しいイベントを除去する?
然し、これの問題点は唯の fork と、
本当にジョブとして起動したコマンドの区別が付かないという事。

振る舞いの違いとしては trap handler の中で発生したfork に対応するジョブの
情報は trap handler を抜けた時に消滅しているという事である。

但し、バックグラウンドとして起動したコマンドのジョブ情報もtrap handler を
抜けると消えてしまうのかもしれない。試せば分かるが面倒なので必要になった
ら確認する事にする。

b もう一つの方法はシグナルを処理している時は
jobs の更新は行わないという物。これが妥当な気がする。

? この現象が起こるのは WINCH だけなのか、或いは別のシグナルでも発生するのか。
→確認した所、INT でも同様にジョブ情報に fork が乗る様である。

trap '(true); jobs' INT

? 現在シグナルの中にいるかどうかを判定する方法は存在するだろうか。
或いは ble.sh の枠組みの中で trap-handler 経由で呼び出されたか
どうかの情報を用いて判定する?

trap-handler の中にいるかどうかの判定方法。一つは return を
使って関数を抜けた時に、直前の exit status を返すか、
或いは固定の exit status を返すかを見るという方法。
よく考えたらこれは bash-4.4 以降でしか使えない。
Bash はこの部分について振る舞いを変更したのだった。

% 取り敢えず b の方向で実装する事にする。
% ble.sh の中での jobs の仕様実態について確認する。
%
% どうやら指定した名称に対応する jobs が存在するかどうかの確認にも
% jobs -- "$value" を使用している様である。これについては、偶々
% value に一致する終了したジョブ名が存在すると jobs -- "$value" を実行する事によって
% その情報がジョブ情報のリストから削除されてしまう。この問題を回避する為に
% jobs -- "$value" を実行する為に ble/util/joblist.check を実行しているが、
% trap handler の中で joblist.check をスキップしてしまうと、
% そのジョブ情報が正しく拾われずに消滅してしまう可能性が残る。
% trap handler の内部では jobs はサブシェルで実行するのが良い気がする。
%
% 1 done: 何れにしても最初に trap handler の中で実行しているかどうかを確認す
% る必要がある。特に ble.sh の実装が原因で発生する変なメッセージを防げれば
% 良いので、trap/.handler の中でローカル変数を定義する事にする。
%
% 2 done: jobs を使っている箇所を確認する。
%
% * util.sh は ble/util/joblist だけでしか jobs を呼び出していない。修正した。
% * core-syntax.sh も ble/syntax/highlight/cmdtype/.is-job-name だけで使っ
% ている。対策した。
% * edit.sh では ble/builtin/exit で終了する時にユーザに確認を求める所で実
% 行しているが、exit する時には何れにしてもジョブ一覧を出力するので敢えて
% 直接実行する。変なジョブ情報が出力される事になってしまうがこれは仕方が
% ない。
% * 他に ble/widget/command-help/.type で jobs -- "" を実行している。これに
% ついても修正を行った。
%
% 3 動作確認: さて、実際に修正して見た所直っていない。どうも trap を抜けた後
% も変なジョブ情報は残っている様である。ユーザのコマンドとして jobs を実行
% すれば変なジョブは消えてなくなっているが、bind -x の中から jobs を呼び出
% すと全て出力されてしまうという事だろうか。
%
% サブシェルの中で jobs を実行する様にした結果か、余計に大量の偽ジョブが登
% 録されてしまっている。
%
% 改めて bind -x を組み合わせた時の動作についても確認する→うーん。再現した…。
% WINCH の直後の bind -x の中で jobs を実行すると偽情報が出る。
% 別の bind -x を一回実行してから次の bind -x で jobs を実行しても再現する。
% bind -x 以外の入力を行った後でも、bind -x の中で jobs を実行すると再現する。
% 一回でもユーザコマンドを (空でも良いので) 実行すると、偽情報は出なくなる。
%
% こうなって来ると変なジョブ情報が消えるのを待つ作戦に頼るのは困難である。
% 今までの変更は取り敢えずなかった事にする。

うーん。trap/.handler の中で jobs を敢えて実行して結果が描画に回る前に
偽情報をクリアしてしまう事にする。blehook WINCH を実行する前に joblist 更新をして、
更に実行した直後にも joblist の更新を行う。二回目の joblist の更新では、
一時的に現れてそれで直ぐに消滅したイベントはイベントとして登録しない事にした。

これだと blehook WINCH を実行している最中に終了した本当のジョブ終了の情報が
消滅すrことになるが、実際に blehook を実行している途中に jobs の状態変化を
Bash が受信するのか不明だし、もしそうだとしても blehook WINCH の処理のよう
なごく短時間でその様な事が起こる確率は低いと考えられる。なので、気にしない
事にする。

取り敢えず動いてはいる様子である。

2020-12-14

* progcomp: : や = の quote の取り扱い (reported by eximus) [#D1434]
* progcomp: : や = の quote の取り扱い (reported by 3ximus) [#D1434]
https://github.com/akinomyoga/ble.sh/issues/77

? そもそも \=, \: の様にエスケープしていたのは何故だったか。
Expand Down Expand Up @@ -3796,7 +3904,7 @@ bash_tips
* 二分探索で調べるというのは複雑な気がする。元の文字列について途中で切
断して二分探索していくという手も考えられるが、変数名の途中など変な所
で切断すると内容が空になるなどして意図しない結果になってしまう。

* 取り敢えず 1 unit (simple word element) ずつ読み取って行って、切断す
るという方法? 然し、'...' 等の様に一気に読み取る事ができるliteral 等
になっているとすると、実装が複雑になる。面倒である。そもそも処理が複
Expand Down

0 comments on commit bc4735e

Please sign in to comment.