skywind3000/asyncrun.vim

source $MYVIMRC when Async runing background cause infinite prompt error messge

Opened this issue · 4 comments

Error detected while processing function AsyncRun_Job_OnTimer:
line 11:
E716: Key not present in Dictionary: "once == 0"
Press ENTER or type command to continue
Error detected while processing function AsyncRun_Job_OnTimer:

I ran into the above when using AsyncRun in a post-update hook of junegunn/vim-plug. Along the lines of:

function! BuildNodeJs(info)
  command! -bang -buffer -nargs=* -bar Make AsyncRun -program=make @ <args>
  execute 'Make'
endfunction
Plug 'nodejs/node', { 'do': function('BuildNodeJs') }

And calling :PlugUpdate.
I didn't get an infinite prompt as in OP though, only 4-5 times. I'll try to figure out the problem or a workaround.

EDIT: The contents of the s:async_info dictionary printed line 558 just before the if s:async_info.once == 0:

{'qfid': -1, 'post': '', 'text': '', 'postsave': ''}

I'll keep looking around for the logic bug or a workaround.

Internal states have been reseted when sourcing your asyncrun.vim

make sure to use AsyncStop before reloading asyncrun.vim

Found a workaround in my case, no more apparent problems.

To my knowledge I didn't source asyncrun.vim a second time, as I call AsyncRun only once within the junegunn/vim-plug post-update hook in that BuildNodeJs function I wrote above, which runs within one of vim-plug's jobs/threads:

Plug 'skywind3000/asyncrun.vim', { 'on': ['AsyncRun!', 'AsyncRun'] }

I realized vim-plug already updates the plugins asynchronously, so, there was no point in using AsyncRun on top of that in async mode, it should be fine sync. So my workaround is to use -mode=term -pos=tab -program=make instead of just -program=make:

command! -bang -nargs=* -bar Make AsyncRun -mode=term -pos=tab -program=make @ <args>

I'm using Vim 8.2. Both vim-plug and AsyncRun appear to use the Vim +job features, and somehow... there is a concurrency issue beyond my understanding. Like s:async_info is indeed populated but isn't accessible in the relevant +job thread? Or, maybe asyncrun.vim is is indeed sourced a 2nd time, somehow, which my tracing seems to indicate. Anyway, problem solved for me with the sync -mode=term workaround.

If curious, some tracing messages in my testing:

asyncrun_support = 1
asyncrun_support = 1  <---- let g:/s:asyncrun_support = 1 is top-level
cwd:
mode:
save:
program:make
command:
s:run called
l:mode: 0 s:asyncrun_support: 1
setting async_info dictionary
asyncrun_support = 1  <---- top-level is parsed/executed again, resetting async_info?
{'qfid': -1, 'post': '', 'text': '', 'postsave': ''}
Error detected while processing function AsyncRun_Job_OnTimer:
line   12:
E716: Key not present in Dictionary: "once == 0"
{'qfid': -1, 'post': '', 'text': '', 'postsave': ''}
Error detected while processing function AsyncRun_Job_OnTimer:

That apparent second parsing also appears when using the sync -mode=term, but there are no apparent problems. Everything runs just fine now.

That apparent second parsing also appears when using the sync -mode=term, but there are no apparent problems. Everything runs just fine now.

Turns out that in my case asyncrun.vim is indeed sourced a second time. When I tried to use -post it wouldn't be called as the internal states had been reset as skywind3000 said. So there are problems when I use a feature that needs those internal states.

Would you consider adding a header guard to plugin/asyncrun.vim to prevent the file from being sourced again, analogous to the headers seen in Vim ftplugin and compiler files? I have no more problems with this header guard, the internal states are not reset. Should fix the OP's problem too?

if exists('g:sourced_asyncrun_plugin') | finish | endif
let g:sourced_asyncrun_plugin = 1

In my case I am unable to tell how/why it is being sourced a second time. I had changed:

Plug 'skywind3000/asyncrun.vim', { 'on': ['AsyncRun!', 'AsyncRun'] }

To:

Plug 'skywind3000/asyncrun.vim'

Yet somehow plugin/asyncrun.vim is somehow sourced a second time, after the exit of BuildNodeJs() (which called/initiated AsyncRun). So I guess this may have something to do with AsyncRun being nested within a vim job which vim-plug uses? I trigger this problem by manually calling :PlugInstall! node, which is after my $VIMRC had loaded:

Plug 'nodejs/node', { 'do': function('BuildNodeJs') }

Anyway, the proposed header guard fixes the problem for me.