Socket::flushData function, multi-threaded data sending order issue
csenjoy opened this issue · 3 comments
csenjoy commented
获取待发送send_buf_sending_tmp
decltype(_send_buf_sending) send_buf_sending_tmp;
{
// 转移出二级缓存
LOCK_GUARD(_mtx_send_buf_sending);
if (!_send_buf_sending.empty()) {
send_buf_sending_tmp.swap(_send_buf_sending);
}
}
发送逻辑
while (!send_buf_sending_tmp.empty()) {
auto &packet = send_buf_sending_tmp.front();
auto n = packet->send(sock, _sock_flags);
......
}
多线程环境下(例如,用户调用send触发的flushData和EventPoller触发的flushData)都能获取一个send_buf_sending_tmp发送。
这种情况下,可能会存在后添加的Buffer::Ptr被先发送的情况。
csenjoy commented
//socket可写,则调用flushData写数据到socket
if (_sendable) {
return flushData(sock_fd_->rawFd(), sock_fd_->type(), false);
}
Socket注册写事件的时候,_sendable被设置为false了,并不会造成多线程访问flushData
csenjoy commented
_sendable作为限制用户调用flushData时,默认情况应该是false。因为默认情况下Socket会注册写事件回调
//标记该socket是否可写,socket写缓存满了就不可写
std::atomic<bool> _sendable {true};
修改为
//标记该socket是否可写,socket写缓存满了就不可写
std::atomic<bool> _sendable {false};
xia-chu commented
嗨 Socket不是线程安全的 现在在zlmediakit中所有的socket操作都能保证在其归属poller线程执行了
但是由于历史原因 并没有在Socket中做线程检查等限制工作
建议先poller->async 然后再执行Socket的send函数