You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
原因大致搞明白了,这个不是被系统信号唤醒的,是因为断点单步调试的时候唤醒的,不调试的情况下不会醒。但有一个问题是当有新连接进来要Accept的时候,会同时唤醒好多个线程。因为他们等待的是同一个epoll以及同一个ListenSocket,任何发生在上面的事件都会通知到所有线程,所以被唤醒了。解决思路有两个:
1.给每个线程创建自己的epoll对象和ListenSocket(需设置端口重用,必须在主线程中创建并listen),对于server端建议使用这个模式,可以实现多线程同时贞听,新连接进来的时候会平均分配到不同的线程上去。
2.通过信号量TSemaphore或临界区TMutex,每次只允许一个线程执行epoll_wait,对client端可以使用这个办法,也就是当一个线程执行read/write的时候,另一个线程去执行epoll_wait,同理,如果有大量read/write的时候,哪这些线程就可以去并发执行read/write了。参考代码如下:
EpoolMutex.Acquire;
while True do
begin
LRet := epoll_wait(FEpollHandle, @FEventList[0], MAX_EVENT_COUNT, cNetworkThreadIdleTime);
if (LRet < 0) then
begin
LRet := GetLastError;
if LRet = EINTR then //EINTR, epoll_wait 调用被系统信号打断, 可以进行重试
Continue
else if LRet = ETIMEDOUT then //等待超时
begin
FreeMemory(GetMemory(1)); //释放内存
Continue;
end
else
begin
sleep(1);
Continue;
end;
end
else
Break;
end;
EpoolMutex.Release;
发现cross里这个epoll_wait真的不阻塞,在没完没了的返回-1,GetLastError=EINTR,也就是所有线程都在空转了,这个应该会占掉不少cpu,影响性能,怎么解决?
Net.CrossSocket.Epoll.pas里的function TEpollCrossSocket.ProcessIoEvent: Boolean;
LRet := epoll_wait(FEpollHandle, @FEventList[0], MAX_EVENT_COUNT, -1);
if (LRet < 0) then
begin
LRet := GetLastError;
// EINTR, epoll_wait 调用被系统信号打断, 可以进行重试
Exit(LRet = EINTR);
end;
The text was updated successfully, but these errors were encountered: