diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2018-01-07 10:16:39 +0100 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2018-04-12 18:22:47 +0200 |
commit | aea079a25df1df5c94e97adf3c92ead397168e27 (patch) | |
tree | 074dd870dc27ec4a598b7d317a6bad3c9e7ceea9 | |
parent | 2cbeb7ca56503ebc203a7fae469d3ede9a5d80da (diff) | |
download | rneovim-aea079a25df1df5c94e97adf3c92ead397168e27.tar.gz rneovim-aea079a25df1df5c94e97adf3c92ead397168e27.tar.bz2 rneovim-aea079a25df1df5c94e97adf3c92ead397168e27.zip |
channels: delay free so that libuv can cleanup handles
add test for a crash this caused
-rw-r--r-- | src/nvim/channel.c | 8 | ||||
-rw-r--r-- | test/functional/core/job_spec.lua | 15 |
2 files changed, 21 insertions, 2 deletions
diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 2e32af2e9a..f31ba424f5 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -245,7 +245,8 @@ void channel_incref(Channel *channel) void channel_decref(Channel *channel) { if (!(--channel->refcount)) { - multiqueue_put(main_loop.fast_events, free_channel_event, 1, channel); + // delay free, so that libuv is done with the handles + multiqueue_put(main_loop.events, free_channel_event, 1, channel); } } @@ -286,12 +287,15 @@ static void channel_destroy_early(Channel *chan) if ((chan->id != --next_chan_id)) { abort(); } + pmap_del(uint64_t)(channels, chan->id); + chan->id = 0; if ((--chan->refcount != 0)) { abort(); } - free_channel_event((void **)&chan); + // uv will keep a reference to handles until next loop tick, so delay free + multiqueue_put(main_loop.events, free_channel_event, 1, chan); } diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 6d4cadbdc8..24bff423df 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -640,6 +640,21 @@ describe('jobs', function() ok(string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set") ~= nil) end) + it('does not crash when repeatedly failing to start shell', function() + source([[ + set shell=nosuchshell + func! DoIt() + call jobstart('true') + call jobstart('true') + endfunc + ]]) + -- The crash only triggered if both jobs are cleaned up on the same event + -- loop tick. This is also prevented by try-block, so feed must be used. + feed_command("call DoIt()") + feed('<cr>') -- press RETURN + eq(2,eval('1+1')) + end) + it('jobstop() kills entire process tree #6530', function() command('set shell& shellcmdflag& shellquote& shellpipe& shellredir& shellxquote&') |