Skip to content
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

Does RpcClientStream::on_close() can call the user callback immediately when hold the _stream_map_lock of RpcClientImpl? #6

Closed
gzc9047 opened this issue Jun 1, 2014 · 2 comments

Comments

@gzc9047
Copy link

gzc9047 commented Jun 1, 2014

If so and user retry in the callback then may deadlock in RpcClientImpl::FindOrCreateStream because of the Reentrant of _stream_map_lock.

@qinzuoyan
Copy link
Collaborator

你可能认为这样的调用轨迹会造成死锁:

  1. RpcClientImpl::StopStreams() ,加锁 _stream_map_lock,然后close所有stream;
  2. RpcClientStream::on_closed()中,调用所有未完成的cntl->Done();
  3. Done()中调用用户回调函数,用户在回调函数中再次发送请求,调用RpcClientImpl::CallMethod();
  4. CallMethod()中调用RpcClientImpl::FindOrCreateStream(),对_stream_map_lock加锁——由于1中已经加锁,造成死锁。

实际上,这里不会死锁,因为:

  1. 用户callback总是在callback_thread中执行的,即1、2和3、4不会在同一个线程中完成,不会死锁,只会竞锁。可以查看RpcChannelImpl::DoneCallback()函数,这里是真正调用用户callback的地方,如果是异步调用的话(用户设置了callback函数),Done最终是调用到了这里。里面将对用户callback的调用post到了CallbackThreadGroup中。
  2. RpcClientImpl::_is_running从一定程度上避免了上述问题的发生:
  3. RpcClientImpl::CallMethod()首先会检查is_runing状态;
  4. RpcClientImpl::StopStreams()只在RpcClientImpl::Stop()中被调用,而且调用之前,已经设置了“_is_running = false”;
  5. 但这里不能完全保证,只是一种优化:如果要完全保证,需要在RpcClientImpl::CallMethod()中对_start_stop_lock加锁,与RpcClientImpl::Stop()中对_is_runing的设置形成互斥。在实现时,考虑到加锁会影响性能,在保证不出问题的情况下,CallMethod()中并没有对_start_stop_lock加锁。

谢谢提醒,是否解释了你的疑问?

@gzc9047
Copy link
Author

gzc9047 commented Jun 2, 2014

Confirm with Zuoyan, this scene will not happened. Please close it.
Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants