We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
timer callback 内で job を起動すると、exit-cb の実行が最大で updatetime の時間分遅れます。
updatetime
ある程度大きなテキストファイルを用意する。
sample.txt
$ yes | head -c 100000 > sample.txt
sample.vim
fu! Task() call substitute(join(readfile('sample.txt'), ''), '.', 'x', 'g') endfu fu! ExitCb(job, status) let elapsed = reltimestr(reltime(s:starttime)) echom printf('EXIT: %s', elapsed) endfu fu! JobStart(...) let s:starttime = reltime() let s:job = job_start('echo', {'exit_cb': 'ExitCb'}) call Task() endfu call timer_start(100, 'JobStart')
vim --clean -S sample.vim
何も入力せずに放置する。
EXIT: 3.969833
コマンドは echo なので即座に終了するはずだが、おおよそ updatetime 経過後に exit-cb が実行される。
echo
再現しない場合は sample.txt のサイズを増やして試してみてください。
macOS と Linux の TUI で確認。GUI は (おそらく) 問題ない。
timer callback 内部で job-channel が close されてしまうため。
mch_inchar()
parse_queued_message()
has_pending_job()
WaitForChar()
wait_time = updatetime
ui_wait_for_chars_or_timer()
JobStart()
Task()
substitute()
ポイントは substitute() 内で job-channel が閉じられてしまう点。 関数内部の line_breakcheck() から RealWaitForChar() が呼ばれ、この中で channel_read() が実行されています。 再現サンプルでは、substitute() 実行中に job のプロセス (echo) を終了させるためにある程度大きなファイルを処理させて時間を稼いでいます。
line_breakcheck()
RealWaitForChar()
channel_read()
substitute() 以外でも、内部で RealWaitForChar() 呼び出しが発生するような処理を置くことで同様に再現すると思います。
The text was updated successfully, but these errors were encountered:
https://github.com/vim/vim/compare/master...ichizok:fix/job-in-timer.diff
os_unix.c の mch_breakcheck() で、RealWaitForChar() が呼ばれた後に parse_queued_messages() を呼んで job/channel をチェックする。
mch_breakcheck()
parse_queued_messages()
Sorry, something went wrong.
Fix slow content update in gina-status (Vim 8)
65015c3
Ref: vim-jp/issues#1164
e97e1a2
PRed. vim/vim#3783
Pending jobs or channels がある場合は WaitForChar() からすぐに戻るようにして、parse_queued_message() を呼ぶ機会を増やしました。
8.1.0710 vim/vim@c46af53
No branches or pull requests
質問・報告の内容
timer callback 内で job を起動すると、exit-cb の実行が最大で
updatetime
の時間分遅れます。再現手順
ある程度大きなテキストファイルを用意する。
sample.txt
sample.vim
vim --clean -S sample.vim
何も入力せずに放置する。
コマンドは
echo
なので即座に終了するはずだが、おおよそupdatetime
経過後に exit-cb が実行される。再現しない場合は sample.txt のサイズを増やして試してみてください。
OSの種類/ディストリ/バージョン
macOS と Linux の TUI で確認。GUI は (おそらく) 問題ない。
原因
timer callback 内部で job-channel が close されてしまうため。
mch_inchar()
に入るこの場合、job の exit-cb (終了検知) は以下の
parse_queued_message()
内で実行されるhttps://github.com/vim/vim/blob/master/src/os_unix.c#L419
has_pending_job()
は FALSEhttps://github.com/vim/vim/blob/master/src/os_unix.c#L469-L470
よって、
WaitForChar()
でwait_time = updatetime
時間分入力を待つWaitForChar()
→ui_wait_for_chars_or_timer()
内で timer callback が実行されるhttps://github.com/vim/vim/blob/master/src/ui.c#L234
JobStart()
) 内で job が起動するTask()
内のsubstitute()
内で job-channel が読み取られ (EOF到達で) close されるWaitForChar()
から戻る契機が (ユーザ入力以外) なくなり、updatetime
経過でタイムアウトするまでparse_queued_message()
が実行されないポイントは
substitute()
内で job-channel が閉じられてしまう点。関数内部の
line_breakcheck()
からRealWaitForChar()
が呼ばれ、この中でchannel_read()
が実行されています。再現サンプルでは、
substitute()
実行中に job のプロセス (echo
) を終了させるためにある程度大きなファイルを処理させて時間を稼いでいます。substitute()
以外でも、内部でRealWaitForChar()
呼び出しが発生するような処理を置くことで同様に再現すると思います。The text was updated successfully, but these errors were encountered: