New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug about redis/socket module #51

Closed
wesom opened this Issue Oct 26, 2013 · 8 comments

Comments

Projects
None yet
2 participants
@wesom

wesom commented Oct 26, 2013

the debug info:
[64000010] lua call [0 to :64000010 : 0 msgsz = 24] error : ./lualib/skynet.lua:81: ./lualib/socket.lua:241: assertion failed!
stack traceback:
[C]: in function 'assert'
./lualib/socket.lua:241: in function 'lock'
./lualib/redis.lua:112: in function 'get'
调用场景:A,B两个service,B有db连接,A 先send消息给 B写数据, A 再call B读取数据,会出现上述bug信息,如果把第一步send改为call方式则正常。如果多次send再call,会读到错误数据。

@cloudwu

This comment has been minimized.

Show comment
Hide comment
@cloudwu

cloudwu Oct 28, 2013

Owner

对 redis 连接的处理, 利用了 socket 库中的锁机制. 对同一条连接, 可以通过加锁来保证不同的 coroutine 依次去完成一个完整的业务(写一次,读一次)

  1. 我按描述写了测试程序, 无法重现错误.
  2. 从 assert 信息看, 是由于同一个 coroutine 连续发起了两次 lock 请求. 但是, 按描述, B 每次接收到 A 的请求, 无论是 send 还是 call 都会生成一个新的 coroutine . 按设计, 第 2 次 call 的时候会因为第一次 send 引发的写操作正在执行而等待解锁, call 和 send 两个请求不应该在同一个 coroutine 内, 不会导致 assert 发生.

请帮忙检查一下具体问题.

多次 send 再 call , 会因为多次 send 的写操作解锁次序随机而后发的操作先执行. 这是不合理的, 我正在修复这个 bug , 让加锁和解锁有序.

Owner

cloudwu commented Oct 28, 2013

对 redis 连接的处理, 利用了 socket 库中的锁机制. 对同一条连接, 可以通过加锁来保证不同的 coroutine 依次去完成一个完整的业务(写一次,读一次)

  1. 我按描述写了测试程序, 无法重现错误.
  2. 从 assert 信息看, 是由于同一个 coroutine 连续发起了两次 lock 请求. 但是, 按描述, B 每次接收到 A 的请求, 无论是 send 还是 call 都会生成一个新的 coroutine . 按设计, 第 2 次 call 的时候会因为第一次 send 引发的写操作正在执行而等待解锁, call 和 send 两个请求不应该在同一个 coroutine 内, 不会导致 assert 发生.

请帮忙检查一下具体问题.

多次 send 再 call , 会因为多次 send 的写操作解锁次序随机而后发的操作先执行. 这是不合理的, 我正在修复这个 bug , 让加锁和解锁有序.

@cloudwu

This comment has been minimized.

Show comment
Hide comment
@cloudwu

cloudwu Oct 28, 2013

Owner

我改写了 lock 的实现,增加了队列. 但我无法重现案例 1.
请测试一下是否还会出现 assert

Owner

cloudwu commented Oct 28, 2013

我改写了 lock 的实现,增加了队列. 但我无法重现案例 1.
请测试一下是否还会出现 assert

@wesom

This comment has been minimized.

Show comment
Hide comment
@wesom

wesom Oct 29, 2013

案例1的描述不太准确,我自己特别写了一个测试用例,简单设置一个key, agent -> A , dbproxy-> B
step 1: A call B
step 2: A send B
step 3: A call B
我用python简单模拟客户端发送3个消息包,每次均可重现案例1(出现之前的bug info),更新queue lock补丁后虽然不再直接报错,但第3步的call无返回,且再次登录不响应任何消息
先report下测试情况,目前还在阅读源码,暂不清楚真正原因

wesom commented Oct 29, 2013

案例1的描述不太准确,我自己特别写了一个测试用例,简单设置一个key, agent -> A , dbproxy-> B
step 1: A call B
step 2: A send B
step 3: A call B
我用python简单模拟客户端发送3个消息包,每次均可重现案例1(出现之前的bug info),更新queue lock补丁后虽然不再直接报错,但第3步的call无返回,且再次登录不响应任何消息
先report下测试情况,目前还在阅读源码,暂不清楚真正原因

@wesom

This comment has been minimized.

Show comment
Hide comment
@wesom

wesom Oct 29, 2013

默认call --> read,send --> write

wesom commented Oct 29, 2013

默认call --> read,send --> write

@cloudwu

This comment has been minimized.

Show comment
Hide comment
@cloudwu

cloudwu Oct 29, 2013

Owner

不响应多半是因为 unlock 没执行到,后续操作获得不了锁的缘故。请结合测试程序查一下。

在 2013年10月29日星期二,wesom 写道:

默认call --> read,send --> write


Reply to this email directly or view it on GitHubhttps://github.com/cloudwu/skynet/issues/51#issuecomment-27292453
.

http://blog.codingnow.com

Owner

cloudwu commented Oct 29, 2013

不响应多半是因为 unlock 没执行到,后续操作获得不了锁的缘故。请结合测试程序查一下。

在 2013年10月29日星期二,wesom 写道:

默认call --> read,send --> write


Reply to this email directly or view it on GitHubhttps://github.com/cloudwu/skynet/issues/51#issuecomment-27292453
.

http://blog.codingnow.com

@cloudwu

This comment has been minimized.

Show comment
Hide comment
@cloudwu

cloudwu Oct 29, 2013

Owner

这个问题可能和复用 coroutine 处理消息有关. 我明天再仔细查一下.

Owner

cloudwu commented Oct 29, 2013

这个问题可能和复用 coroutine 处理消息有关. 我明天再仔细查一下.

cloudwu added a commit that referenced this issue Oct 30, 2013

@wesom

This comment has been minimized.

Show comment
Hide comment
@wesom

wesom Oct 30, 2013

测试通过,不过修复的有点小问题,self.__mode在lock时,应该是false or write or read
assert(not self.__mode and (mode == "read" or mode == "write")) -->
assert(mode == "read" or mode == "write") 否则测试中会报错

wesom commented Oct 30, 2013

测试通过,不过修复的有点小问题,self.__mode在lock时,应该是false or write or read
assert(not self.__mode and (mode == "read" or mode == "write")) -->
assert(mode == "read" or mode == "write") 否则测试中会报错

cloudwu added a commit that referenced this issue Oct 30, 2013

@cloudwu

This comment has been minimized.

Show comment
Hide comment
@cloudwu

cloudwu Oct 30, 2013

Owner

不太建议用 batch 模式, 而且这个模式在很多别的 redis driver 实现中也是没有的. 有同学建议去去掉.
如果制作 db proxy , 建议实现成一个连接池, 每个 db 请求收到后找一个空闲的连接,在上面进行操作.

Owner

cloudwu commented Oct 30, 2013

不太建议用 batch 模式, 而且这个模式在很多别的 redis driver 实现中也是没有的. 有同学建议去去掉.
如果制作 db proxy , 建议实现成一个连接池, 每个 db 请求收到后找一个空闲的连接,在上面进行操作.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment