mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	fix(stream): do not close handle if it is already closing (#26537)
uv_close asserts that a handle is not already closing. We can guard against this assertion failure by manually checking the handle's closing status ourselves.
This commit is contained in:
		@@ -128,15 +128,22 @@ void stream_may_close(Stream *stream)
 | 
			
		||||
void stream_close_handle(Stream *stream)
 | 
			
		||||
  FUNC_ATTR_NONNULL_ALL
 | 
			
		||||
{
 | 
			
		||||
  uv_handle_t *handle = NULL;
 | 
			
		||||
  if (stream->uvstream) {
 | 
			
		||||
    if (uv_stream_get_write_queue_size(stream->uvstream) > 0) {
 | 
			
		||||
      WLOG("closed Stream (%p) with %zu unwritten bytes",
 | 
			
		||||
           (void *)stream,
 | 
			
		||||
           uv_stream_get_write_queue_size(stream->uvstream));
 | 
			
		||||
    }
 | 
			
		||||
    uv_close((uv_handle_t *)stream->uvstream, close_cb);
 | 
			
		||||
    handle = (uv_handle_t *)stream->uvstream;
 | 
			
		||||
  } else {
 | 
			
		||||
    uv_close((uv_handle_t *)&stream->uv.idle, close_cb);
 | 
			
		||||
    handle = (uv_handle_t *)&stream->uv.idle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  assert(handle != NULL);
 | 
			
		||||
 | 
			
		||||
  if (!uv_is_closing(handle)) {
 | 
			
		||||
    uv_close(handle, close_cb);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
local helpers = require('test.functional.helpers')(after_each)
 | 
			
		||||
local thelpers = require('test.functional.terminal.helpers')
 | 
			
		||||
local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim,
 | 
			
		||||
  testprg, ok, source, write_file, mkdir, rmdir = helpers.clear,
 | 
			
		||||
  helpers.eq, helpers.eval, helpers.exc_exec, helpers.feed_command, helpers.feed,
 | 
			
		||||
@@ -1140,6 +1141,31 @@ describe('jobs', function()
 | 
			
		||||
      command('call jobstop(' .. other_jobid .. ')')
 | 
			
		||||
    end)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('does not close the same handle twice on exit #25086', function()
 | 
			
		||||
    local filename = string.format('%s.lua', helpers.tmpname())
 | 
			
		||||
    write_file(filename, [[
 | 
			
		||||
      vim.api.nvim_create_autocmd('VimLeavePre', {
 | 
			
		||||
        callback = function()
 | 
			
		||||
          local id = vim.fn.jobstart('sleep 0')
 | 
			
		||||
          vim.fn.jobwait({id})
 | 
			
		||||
        end,
 | 
			
		||||
      })
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    local screen = thelpers.setup_child_nvim({
 | 
			
		||||
      '-i', 'NONE',
 | 
			
		||||
      '-u', filename,
 | 
			
		||||
      '+q'
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    screen:expect{grid=[[
 | 
			
		||||
                                                        |
 | 
			
		||||
      [Process exited 0]{1: }                               |
 | 
			
		||||
                                                        |*4
 | 
			
		||||
      {3:-- TERMINAL --}                                    |
 | 
			
		||||
    ]]}
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
describe("pty process teardown", function()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user