job_start() してすぐに job_stop() すると job プロセスを終了できない場合がある #969

Closed
ichizok opened this Issue Oct 15, 2016 · 5 comments

Projects

None yet

2 participants

@ichizok
Member
ichizok commented Oct 15, 2016

vim/vim#1155
本家の issue に出たので

原因は #820 (comment) の2です。
win32 では問題ないようです。

再現スクリプト:

let job = job_start(['sleep', '3'])
call assert_equal('run', job_status(job))
echom 'job:' string(job)
" sleep 1m
call job_stop(job)
sleep 10m
call assert_equal('dead', job_status(job))
echom empty(v:errors) ? 'Passed' : string(v:errors)
@ichizok
Member
ichizok commented Oct 15, 2016

https://gist.github.com/ichizok/26d571401be0685267ebf0790e964903
子プロセス側で execvp() する場合は fork() 前にPIDを保存し、deathtrap() 内で getpid() と異なっている場合はすぐ exit() する

@ichizok
Member
ichizok commented Oct 16, 2016 edited

Mac だとたまに失敗する。→ Linux でも同様
どうも fork() が完了する前 (子プロセス側の if 節に到達してない) にシグナルを受信する場合があるようで、
そのとき子プロセス側の deathtrap() 内で呼び出した getpid() は親プロセスと同じPIDを返している。
(getpid() の結果はキャッシュされているので、プロセスの準備が終わってないとそうなる)

@h-east h-east added the kind/bug label Oct 16, 2016
@ichizok
Member
ichizok commented Oct 16, 2016 edited
  • fork 前にフラグ変数を変更して、親は fork 後すぐに戻す。deathtrap() 内でフラグ確認

これで十分かも。 メモリ共有している段階だと親のメモリ領域を参照する?
その他:

  • 親は子のreset_signals が完了するまで待つ
    → fork が遅い環境だと性能に影響する
  • vfork() を使う。Mac の場合、子が execve_exit を実行するまで親は停止するが
    vfork は即座に完了するので性能への影響はない
    → 非推奨の関数。親の動作 (停止するかどうか) が環境依存
  • fork 前に sigprocmask でブロックして、子は reset_signals 完了してからブロック解除する
    → うまくいく。sigprocmask が使えるか configure で確認
@ichizok
Member
ichizok commented Oct 17, 2016

https://groups.google.com/forum/#!topic/vim_dev/tevAPI5T86M
sigprocmask 版で投げました。

@h-east
Member
h-east commented Oct 18, 2016

patch 8.0.0045
vim/vim@bb09ceb

Great👍

@h-east h-east closed this Oct 18, 2016
@h-east h-east added the xlose/fixed label Oct 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment