Calling :CoqJumpToEnd before :CoqStart results in a deadlock on NeoVim. The sequence of events is:
Since !s:running(), :CoqJumpToEnd calls coqtail#start with coqtail#jumpto("endpoint") as a callback.
coqtail#start calls s:call, which calls s:sendexpr and registers coqtail#after_startCB as its callback.
s:chanrecv receives the reply and executes coqtail#after_startCB.
coqtail#after_startCB executes coqtail#jumpto, which calls s:call, which calls s:evalexpr.
s:evalexpr blocks while waiting for a reply, but s:chanrecv is also blocked waiting for coqtail#after_startCB to return.
Commands like :CoqNext don't have this problem because they execute asynchronously, so coqtail#after_startCB calls s:sendexpr instead of s:evalexpr. It also works fine on Vim because it uses the builtin ch_evalexpr, which handles other messages while waiting for a reply.
The ideal solution would be to somehow execute callbacks asynchronously, but I couldn't figure out a way of doing that in vimscript. Perhaps it's possible with Lua. In any case, I realized that the only synchronous commands that could be called before :CoqStart are :CoqJumpToEnd, :CoqJumpToError, and :CoqGotoDef, so I just have these cases busy wait for coqtail#start to complete instead of using callbacks.
Calling
:CoqJumpToEnd
before:CoqStart
results in a deadlock on NeoVim. The sequence of events is:!s:running()
,:CoqJumpToEnd
callscoqtail#start
withcoqtail#jumpto("endpoint")
as a callback.coqtail#start
callss:call
, which callss:sendexpr
and registerscoqtail#after_startCB
as its callback.s:chanrecv
receives the reply and executescoqtail#after_startCB
.coqtail#after_startCB
executescoqtail#jumpto
, which callss:call
, which callss:evalexpr
.s:evalexpr
blocks while waiting for a reply, buts:chanrecv
is also blocked waiting forcoqtail#after_startCB
to return.Commands like
:CoqNext
don't have this problem because they execute asynchronously, socoqtail#after_startCB
callss:sendexpr
instead ofs:evalexpr
. It also works fine on Vim because it uses the builtinch_evalexpr
, which handles other messages while waiting for a reply.The ideal solution would be to somehow execute callbacks asynchronously, but I couldn't figure out a way of doing that in vimscript. Perhaps it's possible with Lua. In any case, I realized that the only synchronous commands that could be called before
:CoqStart
are:CoqJumpToEnd
,:CoqJumpToError
, and:CoqGotoDef
, so I just have these cases busy wait forcoqtail#start
to complete instead of using callbacks.Fixes #360.