Skip to content

Commit 5c55c4e

Browse files
committed
fix(event):去除FdEvent的kHupEvent事件,同时修复之前epoll因EPOLLHUP引起的Loop空跑问题
1 parent a502709 commit 5c55c4e

File tree

4 files changed

+23
-28
lines changed

4 files changed

+23
-28
lines changed

modules/event/engines/epoll/fd_event.cpp

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ bool EpollFdEvent::enable()
7979
if (events_ & kExceptEvent)
8080
++d_->except_event_num;
8181

82-
if (events_ & kHupEvent)
83-
++d_->hup_event_num;
84-
8582
d_->fd_events.push_back(this);
8683

8784
reloadEpoll();
@@ -104,9 +101,6 @@ bool EpollFdEvent::disable()
104101
if (events_ & kExceptEvent)
105102
--d_->except_event_num;
106103

107-
if (events_ & kHupEvent)
108-
--d_->hup_event_num;
109-
110104
auto iter = std::find(d_->fd_events.begin(), d_->fd_events.end(), this);
111105
d_->fd_events.erase(iter);
112106

@@ -136,9 +130,6 @@ void EpollFdEvent::reloadEpoll()
136130
if (d_->except_event_num > 0)
137131
new_events |= EPOLLERR;
138132

139-
if (d_->hup_event_num > 0)
140-
new_events |= EPOLLHUP;
141-
142133
d_->ev.events = new_events;
143134

144135
if (old_events == 0) {
@@ -173,29 +164,34 @@ void EpollFdEvent::OnEventCallback(uint32_t events, void *obj)
173164
tbox_events |= kExceptEvent;
174165
}
175166

167+
bool is_got_hup = false;
168+
176169
if (events & EPOLLHUP) {
177170
events &= ~EPOLLHUP;
178-
tbox_events |= kHupEvent;
171+
is_got_hup = true;
179172
}
180173

181174
//! 要先复制一份,因为在for中很可能会改动到d->fd_events,引起迭代器失效问题
182175
auto tmp = d->fd_events;
183-
for (auto event : tmp)
176+
for (auto event : tmp) {
184177
event->onEvent(tbox_events);
185178

179+
//! 在epoll中,无论有没有监听EPOLLHUP,在对端close了fd时都会触发本端EPOLLHUP事件
180+
//! 只要发生了EPOLLHUB事件,就无法停止它,得强制disable()所有fd关联FdEvent
181+
//! 否则它会一直触发事件,导致Loop空跑,CPU占满问题
182+
if (is_got_hup) {
183+
//! 将HUP事件当成可读事件,上层读到0字节则表示对端已关闭
184+
event->onEvent(kReadEvent);
185+
event->disable(); //! 强制关闭事件
186+
}
187+
}
188+
186189
if (events)
187190
LogWarn("unhandle events:%08X, fd:%d", events, d->fd);
188191
}
189192

190193
void EpollFdEvent::onEvent(short events)
191194
{
192-
/**
193-
* 由于EPOLLHUP会一直触发,所以无论事件有没有监听HupEvent,只要发生了EPOLLHUB事件,
194-
* 对应fd所有的事件都要强制disable()。否则会导致Loop空跑问题。
195-
*/
196-
if (events & kHupEvent)
197-
disable();
198-
199195
if (events_ & events) {
200196
if (is_stop_after_trigger_)
201197
disable();

modules/event/engines/epoll/types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct EpollFdSharedData {
3737
int read_event_num = 0; //!< 监听可读事件的FdEvent个数
3838
int write_event_num = 0; //!< 监听可写事件的FdEvent个数
3939
int except_event_num = 0; //!< 监听异常事件的FdEvent个数
40-
int hup_event_num = 0; //!< 监听挂起事件的FdEvent个数
4140

4241
std::vector<EpollFdEvent*> fd_events;
4342
};

modules/event/fd_event.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class FdEvent : public Event {
3333
kReadEvent = 0x01, //!< 可读事件
3434
kWriteEvent = 0x02, //!< 可写事件
3535
kExceptEvent = 0x04, //!< 异常事件
36-
kHupEvent = 0x08, //!< 断开事件
3736
};
3837

3938
using Event::Event;

modules/event/fd_event_test.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <errno.h>
2525
#include <cstring>
26+
#include <tbox/base/log.h>
2627
#include <tbox/base/log_output.h>
2728

2829
#include "loop.h"
@@ -367,18 +368,18 @@ TEST(FdEvent, Exception)
367368
ASSERT_TRUE(write_fd_event != nullptr);
368369

369370
int run_time = 0;
371+
size_t recv_bytes = 0;
370372

371-
EXPECT_TRUE(read_fd_event->initialize(read_fd, FdEvent::kReadEvent | FdEvent::kHupEvent, Event::Mode::kPersist));
373+
EXPECT_TRUE(read_fd_event->initialize(read_fd, FdEvent::kReadEvent, Event::Mode::kPersist));
372374
read_fd_event->setCallback([&](short events){
373375
if (events & FdEvent::kReadEvent) {
374376
char data[100] = { 0 };
375377
ssize_t len = read(read_fd, data, sizeof(data));
376-
EXPECT_EQ(len, sizeof(int));
377-
}
378-
379-
if (events & FdEvent::kHupEvent) {
380-
++run_time;
381-
loop->exitLoop();
378+
recv_bytes += len;
379+
if (len == 0) {
380+
++run_time;
381+
loop->exitLoop();
382+
}
382383
}
383384
});
384385

@@ -396,10 +397,10 @@ TEST(FdEvent, Exception)
396397

397398
write_fd_event->enable();
398399

399-
loop->exitLoop(std::chrono::milliseconds(10));
400400
loop->runLoop();
401401

402402
EXPECT_EQ(run_time, 1);
403+
EXPECT_EQ(recv_bytes, sizeof(int));
403404

404405
read_fd_event->disable();
405406
write_fd_event->disable();

0 commit comments

Comments
 (0)