Skip to content

Commit

Permalink
histdb: kill orphan sqlite3 processes
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Feb 6, 2023
1 parent 4fac1e3 commit 36e1c89
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 66 deletions.
73 changes: 57 additions & 16 deletions ble.pp
Expand Up @@ -1438,29 +1438,70 @@ function ble/base/initialize-runtime-directory {
# ロード時刻の記録 (ble-update で使う為)
: >| "$_ble_base_run/$$.load"

## @fn ble/base/clean-up-runtime-directory [opts]
## 既に存在しないプロセスに属する実行時ファイルを削除します。*.pid のファイル
## 名を持つ実行時ファイルはについては、子バックグラウンドプロセスのプロセスID
## を含むと見做し、ファイルの内容を読み取ってそれが整数であればその整数に対し
## て kill を実行します。
##
## @param[in,opt] opts
## finalize ... 自プロセス $$ に関連するファイルも削除します。現セッション
## における ble.sh の終了処理時に呼び出される事を想定しています。
##
function ble/base/clean-up-runtime-directory {
local file pid mark removed
mark=() removed=()
local opts=$1 failglob= noglob=
if [[ $- == *f* ]]; then
noglob=1
set +f
fi
if shopt -q failglob &>/dev/null; then
failglob=1
shopt -u failglob
fi

local -a alive=() removed=() bgpids=()
[[ :$opts: == *:finalize:* ]] && alive[$$]=0

local file pid iremoved=0 ibgpid=0
for file in "$_ble_base_run"/[1-9]*.*; do
[[ -e $file ]] || continue
[[ -e $file || -h $file ]] || continue

# extract pid (skip if it is not a number)
pid=${file##*/}; pid=${pid%%.*}
[[ ${mark[pid]+set} ]] && continue
mark[pid]=1
if ! builtin kill -0 "$pid" &>/dev/null; then
removed=("${removed[@]}" "$_ble_base_run/$pid."*)
[[ $pid && ! ${pid//[0-9]} ]] || continue

if [[ ! ${alive[pid]+set} ]]; then
builtin kill -0 "$pid" &>/dev/null
((alive[pid]=$?==0))
fi
((alive[pid])) && continue

# kill process specified by the pid file
if [[ $file == *.pid && -s $file ]]; then
local run_pid IFS= TMOUT=
builtin read "${_ble_bash_tmout_wa[@]}" -r run_pid < "$file"
if [[ $run_pid && ! ${run_pid//[0-9]} ]]; then
if ((pid==$$)); then
# 現セッションの背景プロセスの場合は遅延させる
kill -0 "$run_pid" &>/dev/null && bgpids[ibgpid++]=$run_pid
else
kill "$run_pid"
fi
fi
fi

removed[iremoved++]=$file
done
((${#removed[@]})) && ble/bin/rm -rf "${removed[@]}"
((iremoved)) && ble/bin/rm -rf "${removed[@]}" 2>/dev/null
((ibgpid)) && ({ ble/bin/sleep 3; kill "${bgpids[@]}"; } & disown) &>/dev/null </dev/null

[[ $failglob ]] && shopt -s failglob
[[ $noglob ]] && set -f
return 0
}

# initialization time = 9ms (for 70 files)
if shopt -q failglob &>/dev/null; then
shopt -u failglob
ble/base/clean-up-runtime-directory
shopt -s failglob
else
ble/base/clean-up-runtime-directory
fi
ble/base/clean-up-runtime-directory

##
## @var _ble_base_cache
Expand Down Expand Up @@ -2202,7 +2243,7 @@ function ble/base/unload {
ble/builtin/trap/finalize
ble/util/import/finalize
ble/fd#finalize
ble/bin/rm -rf "$_ble_base_run/$$".* 2>/dev/null
ble/base/clean-up-runtime-directory finalize
return 0
}

Expand Down
2 changes: 1 addition & 1 deletion contrib
Submodule contrib updated 2 files
+3 −3 contrib.mk
+40 −7 histdb.bash
3 changes: 3 additions & 0 deletions docs/ChangeLog.md
Expand Up @@ -544,6 +544,9 @@
- histdb: support auto-complete source `histdb-word` `#D1938` xxxxxxx
- histdb: automatically updrade histdb version `#D1940` xxxxxxx
- histdb: support auto-complete source `histdb-history` `#D1941` xxxxxxx
- histdb: handle multiple exec lines for `histdb_ignore` `#D1942` xxxxxxx
- histdb: kill orphan `sqlite3` processes `#D1943` xxxxxxx
- histdb: back up the database `#D1944` xxxxxxx
- integration: move `fzf` and `bash-preexec` integrations to subdir `#D1939` xxxxxxx

<!---------------------------------------------------------------------------->
Expand Down
152 changes: 103 additions & 49 deletions note.txt
Expand Up @@ -1370,6 +1370,12 @@ bash_tips
bug-bash, third-party bugs & reviews
-------------------------------------------------------------------------------

2023-02-06

* bug-bash: 実は colored-stats は本来 LS_COLORS を反映するらしい。然し、
readline 初期化前に設定されている必要がある。colored-stats も bind 等ではな
くて inputrc 経由で有効にしなければならない様だ。

2023-01-31

* review: bash libraries
Expand Down Expand Up @@ -1893,7 +1899,7 @@ bash_tips
* https://github.com/Powerlevel9k/powerlevel9k
p9k と initial commit が同じなので再実装というよりは fork の気がする。

https://github.com/aristocratos/bashtop
* https://github.com/aristocratos/bashtop
これは最近現れた物で pure bash で色々な UI を実装している。
オプション引数はなく設定は直接編集する様になっている。
背景が明るい時の配色に対応していない。256色要求。
Expand All @@ -1903,7 +1909,7 @@ bash_tips
然し、宣伝の為には見た目を派手にした物も必要なのかもしれない。
* 何故か現れたばかりなのに 6.3k も集まっているし、
一体何が起こるとこのように話題になるのだろうか。不思議である。
HN にも reddit にも対して人気になった物は見られない
HN にも reddit にも大して人気になった物は見られない
何処から広まってどう人気になったのか不明である。
* freebsd, aur, debian, fedora/centos にまでパッケージが在る。

Expand All @@ -1922,33 +1928,6 @@ bash_tips
- leakvars
- keymap の移動 (これは別 commit にする?)

2023-02-05

* histdb: _ble_histdb_exec_ignore の管理をちゃんとする

現在の実装だと複数の exec lines がある時に最後のコマンドの ignore が最初の
コマンドの ignore として使われる事になってしまっている。

* histdb: sqlite3 のプロセスだけ残ってしまったのをどう始末するか。

* sqlite3 のコマンドライン引数に親 pid を含める可能性

考えたが、無駄な文字列を指定できる様な雰囲気はない。と思ったが -cmd を使
えばコメントを指定できるのではないか。然し、その様にしたとしても ps をし
た時に見える様になるだけで、スクリプトから対応する親プロセスを抜き出して
殺すのに使える訳でもない。というか、そもそも sqlite3 のプロセスを列挙する
時点で簡単ではない。なので、これは単に ps をした時に分かりやすいというだ
けの事である。

或いはプロセスツリーで見やすくする為に直接親プロセスから起動して disown
する? と思ったが、やはり無駄なメッセージが表示されてしまう。そもそも、$!
を勝手に書き換えてしまう事になるのでやはり避けたい。

別の方法はプロセスを書き込んでおいて他の ble.sh session がそのファイルを削
除する時に中に書かれているプロセス ID に対して kill を送信するという事。然
し、これも pid 記録ファイルの削除のタイミング等によって変な事にならないかの
懸念が残る。

2023-02-03

* contrib: ble-import で contrib/ は不要なのではないか?
Expand Down Expand Up @@ -1999,26 +1978,6 @@ bash_tips
histdb -g glob コマンドをパターンで絞り込み
hsitdb -r command_id コマンド削除

* histdb: backup機能。sqlite3 データベースが破壊される事が実際起こるのか分か
らないが、消えるとショックなのでバックアップは時々したい。".backup ファイル
名" でバックアップを作れる様だが、バックアップのファイル名は自分で決める必
要がある。またバックアップの頻度も考えたい。取り敢えず終了時に前回のバック
アップから時間が経っていたらバックアップするという形にするのが良い気がする。
前回のバックアップ時刻はデータベース内部に直接記録してしまって良いのでは。

壊れたファイルで上書きしても駄目なので sqlite3 が壊れていないかのチェックも
行う。チェックに失敗したら警告を発する。データサイズが大きくなってくると
"PRAGMA integrity_check;" は時間がかかるらしい。代わりに "PRAGMA
quick_check;" という物があるらしい。

https://sqlite.org/forum/forumpost/9d9e63a8d4
https://serverfault.com/questions/8048/how-can-i-verify-that-a-sqlite-db3-file-is-valid-consistent

.backup を実行するのと直接コピーするので何が違うのかと思ったが、直接コピー
すると中途半端な transaction のデータもコピーしたり、或いは書き換えながらコ
ピーされたりして壊れるという事。
hourly, daily, weekly, monthly ぐらい backup しておけば十分の気がする。

2023-01-25

* complete: 英単語の曖昧補間やスペルミスの検出など
Expand Down Expand Up @@ -6872,6 +6831,101 @@ bash_tips
Done (実装ログ)
-------------------------------------------------------------------------------

2023-02-06

* histdb: backup機能 [#D1944]

sqlite3 データベースが破壊される事が実際起こるのか分からないが、消えるとショッ
クなのでバックアップは時々したい。".backup ファイル名" でバックアップを作れ
る様だが、バックアップのファイル名は自分で決める必要がある。またバックアッ
プの頻度も考えたい。取り敢えず終了時に前回のバックアップから時間が経ってい
たらバックアップするという形にするのが良い気がする。前回のバックアップ時刻
はデータベース内部に直接記録してしまって良いのでは。

壊れたファイルで上書きしても駄目なので sqlite3 が壊れていないかのチェックも
行う。チェックに失敗したら警告を発する。データサイズが大きくなってくると
"PRAGMA integrity_check;" は時間がかかるらしい。代わりに "PRAGMA
quick_check;" という物があるらしい。

https://sqlite.org/forum/forumpost/9d9e63a8d4
https://serverfault.com/questions/8048/how-can-i-verify-that-a-sqlite-db3-file-is-valid-consistent

.backup を実行するのと直接コピーするので何が違うのかと思ったが、直接コピー
すると中途半端な transaction のデータもコピーしたり、或いは書き換えながらコ
ピーされたりして壊れるという事。
hourly, daily, weekly, monthly ぐらい backup しておけば十分の気がする。

と思ったが integrity_check を行うのであれば hourly で十分の気がする。或いは
そんなに頻繁に壊れる物でもないと考えれば daily でも良いのかもしれない。

* histdb: sqlite3 のプロセスだけ残ってしまったのをどう始末するか [#D1943]

* sqlite3 のコマンドライン引数に親 pid を含める可能性

考えたが、無駄な文字列を指定できる様な雰囲気はない。と思ったが -cmd を使
えばコメントを指定できるのではないか。然し、その様にしたとしても ps をし
た時に見える様になるだけで、スクリプトから対応する親プロセスを抜き出して
殺すのに使える訳でもない。というか、そもそも sqlite3 のプロセスを列挙する
時点で簡単ではない。なので、これは単に ps をした時に分かりやすいというだ
けの事である。

或いはプロセスツリーで見やすくする為に直接親プロセスから起動して disown
する? と思ったが、やはり無駄なメッセージが表示されてしまう。そもそも、$!
を勝手に書き換えてしまう事になるのでやはり避けたい。

a 別の方法はプロセスを書き込んでおいて他の ble.sh session がそのファイルを
削除する時に中に書かれているプロセス ID に対して kill を送信するという事。
然し、これも pid 記録ファイルの削除のタイミング等によって変な事にならない
かの懸念が残る。

b うーん。或いは。。sqlite3 のプロセス id で run/histdb.$bgpid.ppid という
ファイルを作って置いて、もし run/histdb.$bgpid.ppid に含まれている親プロ
セスが既に存在していなかったらその sqlite3 プロセスは kill する。

c 或いは本当は $$.histdb.pid というファイル名にして中に記録する方が良い様な
気もするが、それだと ble.sh 本体の方の管理によって削除されてしまうので駄
目。或いは、ble.sh 本体の方で *.pid というファイル名だったら中に書かれて
いるプロセスを削除するというルールにしておくという可能性もある。

うーん。その方が今後類似の事をしたいと思った時に consistent に処理できる
様な気がする。

d reject: 別の可能性としては、一つの sqlite3 プロセスを全体で共有するという
可能性? その様にすれば常に一つのインスタンスだけを持っていれば良いし、一
旦起動したら起動しっぱなしで良い気がするので、わざわざ kill しなくても良
い。と思ったが、そうすると今度は stream の同期の問題が出てくる。複数の
query が混ざり合ってしまうともう駄目になってしまう。そもそも同期の問題を
解決する為に sqlite3 を使っているのだから、やはり sqlite3 をセッションご
とに持つのは避けられない。

この b の方法が良い気がする。と思ったが c の方法にする。

* histdb: _ble_histdb_exec_ignore の管理をちゃんとする [#D1942]

現在の実装だと複数の exec lines がある時に最後のコマンドの ignore が最初の
コマンドの ignore として使われる事になってしまっている。

a 毎回判定する事にする? →それだと途中で設定が変更された時に変な事になる。

b 同じ command_id で既に項目が登録されている時にだけ更新する? →無駄にコマ
ンドを発行する事になる気がする。然し、update を使えば該当する項目がない時
には無視されるだけなので、単に request を一回送信するだけである。

これを考えたら単に _ble_histdb_exec_ignore の現在のチェックを削除するだけ
で良い。そもそもよく考えたら session 情報の更新は histdb_ignore に該当し
たとしても行っておくべきだし、何れにしても request は送るのではないか。

c exec line に追加情報を埋め込める様にする? 然し histdb だけの為に専用のフィー
ルドを用意するのは拡張性がよくない (使いたい項目ごとに拡張を行う必要があ
る) し、別の配列に項目を保存するとしてもインデックスの管理などをどうする
のかが分からない。

と思ったが command_id を使って記録すれば良いだけなのでは? そして使ったら
unset する。

結局 c の方針で実装する事にした。結局 ignore されたコマンドに関しては
session 時刻及び cwd も更新されないがそれで良い事にする。

2023-02-05

* histdb: 同じディレクトリの一番最近の履歴を抽出する [#D1941]
Expand Down

0 comments on commit 36e1c89

Please sign in to comment.