Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lua/opencode/curl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ function M.request(opts)
shutdown = function()
if job and job.pid then
pcall(function()
job:kill('sigterm')
job:kill(15) -- SIGTERM
end)
end
end,
Expand Down
27 changes: 21 additions & 6 deletions lua/opencode/opencode_server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ local function ensure_vim_leave_autocmd()
callback = function()
local state = require('opencode.state')
if state.opencode_server then
state.opencode_server:shutdown():wait(2000)
pcall(function()
state.opencode_server:shutdown():wait(2000)
end)
end
end,
})
Expand Down Expand Up @@ -56,15 +58,27 @@ function OpencodeServer:shutdown()
end

if self.job and self.job.pid then
local job = self.job

self.job = nil
self.url = nil
self.handle = nil

pcall(function()
self.job:kill('sigterm')
job:kill(15) -- SIGTERM
end)

vim.defer_fn(function()
if job and job.pid then
pcall(function()
job:kill(9) -- SIGKILL
end)
end
end, 500)
else
self.shutdown_promise:resolve(true)
end

self.job = nil
self.url = nil
self.handle = nil
self.shutdown_promise:resolve(true)
return self.shutdown_promise
end

Expand Down Expand Up @@ -118,6 +132,7 @@ function OpencodeServer:spawn(opts)
end
end,
}, function(exit_opts)
-- Clear fields if not already cleared by shutdown()
self.job = nil
self.url = nil
self.handle = nil
Expand Down
30 changes: 26 additions & 4 deletions tests/unit/opencode_server_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,39 @@ describe('opencode.opencode_server', function()

it('shutdown resolves shutdown_promise and clears fields', function()
local server = OpencodeServer.new()
server.job = { pid = 2, kill = function() end }
server.url = 'http://x'
server.handle = 2
local exit_callback

-- Mock vim.system to capture the exit callback
vim.system = function(cmd, opts, on_exit)
exit_callback = on_exit
return { pid = 2, kill = function() end }
end

-- Spawn the server so the exit callback is set up
server:spawn({
cwd = '.',
on_ready = function() end,
on_error = function() end,
on_exit = function() end,
})

local resolved = false
server:get_shutdown_promise():and_then(function()
resolved = true
end)

-- Call shutdown (sends SIGTERM)
server:shutdown()
vim.wait(50, function()

-- Simulate the process exiting by calling the exit callback
vim.schedule(function()
exit_callback({ code = 0, signal = 0 })
end)

vim.wait(100, function()
return resolved
end)

assert.is_true(resolved)
assert.is_nil(server.job)
assert.is_nil(server.url)
Expand Down