cloudwu / skynet

A lightweight online game framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

socket.read may never return when socket.close concurrently

t0350 opened this issue · comments

主干最新。

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.

socket 这部分代码写的比较糟糕,我加了个判断处理这种情况。可能更完善的做法是重写相关代码。

ps. 问题出现的根源是太早 close 导致系统的 CLOSE 消息到的时候,closing 流程还没有完成。

另外,在多个 coroutine 混合调用 read 和 close 也不是很好的味道。