socket.read may never return when socket.close concurrently
t0350 opened this issue · comments
t0350 commented
主干最新。
Describe the bug
A clear and concise description of what the bug is.
mongodb 依赖 https://github.com/cloudwu/skynet/blob/master/lualib/skynet/db/mongo.lua#L76 这里的处理逻辑,在 close 后,有几率出现 read 不返回,一直挂起。
To Reproduce
Steps to reproduce the behavior.
修改了 testsocket.lua 的 echo 函数。创建 testsocket 服务后,执行 echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" | nc 127.0.0.1 9001
,执行完毕后使用 debug_console 查看对应服务的 task,会有一个协程停在 read 不退出。
local skynet = require "skynet"
local socket = require "skynet.socket"
local mode , id = ...
local function echo(sid)
skynet.error(">>>>>>")
socket.start(sid)
skynet.fork(function()
local data
skynet.fork(function()
socket.close(sid)
end)
while true do
data = socket.read(sid, 2)
if not data then
print "no more"
break
end
print(data)
end
end)
end
if mode == "agent" then
id = tonumber(id)
skynet.start(function()
skynet.fork(function()
echo(id)
end)
end)
else
local function accept(sid)
skynet.newservice(SERVICE_NAME, "agent", sid)
end
skynet.start(function()
local sid = socket.listen("127.0.0.1", 9001)
print("Listen socket :", "127.0.0.1", 9001)
socket.start(sid , function(id, addr)
print("connect from " .. addr .. " " .. id)
-- you have choices :
-- 1. skynet.newservice("testsocket", "agent", id)
-- 2. skynet.fork(echo, id)
-- 3. accept(id)
accept(id)
end)
end)
end
Additional context
Add any other context about the problem here.
云风 commented
socket 这部分代码写的比较糟糕,我加了个判断处理这种情况。可能更完善的做法是重写相关代码。
ps. 问题出现的根源是太早 close 导致系统的 CLOSE 消息到的时候,closing 流程还没有完成。
另外,在多个 coroutine 混合调用 read 和 close 也不是很好的味道。