Skip to content

Commit 83be14a

Browse files
committed
Added checks to and improved polling.
1 parent daa400f commit 83be14a

File tree

5 files changed

+140
-66
lines changed

5 files changed

+140
-66
lines changed

src/torrent/poll_epoll.cc

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
#include "torrent/utils/log.h"
1515
#include "torrent/utils/thread.h"
1616

17-
#define LT_LOG_EVENT(event, log_level, log_fmt, ...) \
18-
lt_log_print(LOG_SOCKET_##log_level, "epoll->%s(%i): " log_fmt, event->type_name(), event->file_descriptor(), __VA_ARGS__);
17+
#define LT_LOG_EVENT(log_fmt, ...) \
18+
lt_log_print(LOG_CONNECTION_FD, "epoll->%i : %s : " log_fmt, event->file_descriptor(), event->type_name(), __VA_ARGS__);
19+
20+
#define LT_LOG_DEBUG_DATA_FD(log_fmt, ...)
21+
// #define LT_LOG_DEBUG_DATA_FD(log_fmt, ...) \
22+
// lt_log_print(LOG_CONNECTION_FD, "epoll->%i: " log_fmt, itr->data.fd, __VA_ARGS__);
1923

2024
namespace torrent {
2125

@@ -24,9 +28,9 @@ class PollInternal {
2428
using Table = std::vector<std::pair<uint32_t, Event*>>;
2529

2630
inline uint32_t event_mask(Event* e);
31+
inline uint32_t event_mask_any(int fd);
2732
inline void set_event_mask(Event* e, uint32_t m);
2833

29-
void flush_events();
3034
void modify(torrent::Event* event, unsigned short op, uint32_t mask);
3135

3236
int m_fd;
@@ -40,15 +44,39 @@ class PollInternal {
4044

4145
inline uint32_t
4246
PollInternal::event_mask(Event* e) {
43-
assert(e->file_descriptor() != -1);
47+
if (e->file_descriptor() == -1)
48+
throw internal_error("PollInternal::event_mask() invalid file descriptor for event: name:" + std::string(e->type_name()));
49+
50+
if (static_cast<unsigned int>(e->file_descriptor()) >= m_table.size())
51+
throw internal_error("PollInternal::event_mask() file descriptor out of range: name:" + std::string(e->type_name()) + " fd:" + std::to_string(e->file_descriptor()));
52+
53+
if (m_table[e->file_descriptor()].second != e)
54+
throw internal_error("PollInternal::event_mask() event mismatch: name:" + std::string(e->type_name()) + " fd:" + std::to_string(e->file_descriptor()));
55+
56+
return m_table[e->file_descriptor()].first;
57+
}
4458

45-
Table::value_type entry = m_table[e->file_descriptor()];
46-
return entry.second != e ? 0 : entry.first;
59+
inline uint32_t
60+
PollInternal::event_mask_any(int fd) {
61+
if (fd == -1)
62+
throw internal_error("PollInternal::event_mask_any() invalid file descriptor for event");
63+
64+
if (static_cast<unsigned int>(fd) >= m_table.size())
65+
throw internal_error("PollInternal::event_mask_any() file descriptor out of range: fd:" + std::to_string(fd));
66+
67+
return m_table[fd].first;
4768
}
4869

4970
inline void
5071
PollInternal::set_event_mask(Event* e, uint32_t m) {
51-
assert(e->file_descriptor() != -1);
72+
if (e->file_descriptor() == -1)
73+
throw internal_error("PollInternal::set_event_mask() invalid file descriptor for event: name:" + std::string(e->type_name()));
74+
75+
if (static_cast<unsigned int>(e->file_descriptor()) >= m_table.size())
76+
throw internal_error("PollInternal::set_event_mask() file descriptor out of range: name:" + std::string(e->type_name()) + " fd:" + std::to_string(e->file_descriptor()));
77+
78+
if (m_table[e->file_descriptor()].second != e)
79+
throw internal_error("PollInternal::set_event_mask() event mismatch: name:" + std::string(e->type_name()) + " fd:" + std::to_string(e->file_descriptor()));
5280

5381
m_table[e->file_descriptor()] = Table::value_type(m, e);
5482
}
@@ -58,7 +86,7 @@ PollInternal::modify(Event* event, unsigned short op, uint32_t mask) {
5886
if (event_mask(event) == mask)
5987
return;
6088

61-
LT_LOG_EVENT(event, DEBUG, "modify event : op:%hx mask:%hx", op, mask);
89+
LT_LOG_EVENT("modify event : op:%hx mask:%hx", op, mask);
6290

6391
epoll_event e;
6492
e.data.u64 = 0;
@@ -99,7 +127,7 @@ Poll::create() {
99127
auto socket_open_max = sysconf(_SC_OPEN_MAX);
100128

101129
if (socket_open_max == -1)
102-
throw internal_error("Poll::create(): sysconf(_SC_OPEN_MAX) failed: " + std::string(std::strerror(errno)));
130+
throw internal_error("Poll::create() : sysconf(_SC_OPEN_MAX) failed: " + std::string(std::strerror(errno)));
103131

104132
int fd = epoll_create(socket_open_max);
105133

@@ -129,7 +157,7 @@ Poll::do_poll(int64_t timeout_usec) {
129157

130158
if (status == -1) {
131159
if (errno != EINTR)
132-
throw internal_error("Poll::work(): " + std::string(std::strerror(errno)));
160+
throw internal_error("Poll::work() " + std::string(std::strerror(errno)));
133161

134162
return 0;
135163
}
@@ -161,32 +189,42 @@ Poll::process() {
161189
unsigned int count = 0;
162190

163191
for (epoll_event *itr = m_internal->m_events.get(), *last = m_internal->m_events.get() + m_internal->m_waiting_events; itr != last; ++itr) {
164-
// TODO: These should be asserts?
165-
if (itr->data.fd < 0 || static_cast<size_t>(itr->data.fd) >= m_internal->m_table.size())
166-
continue;
192+
if (itr->data.fd < 0)
193+
throw internal_error("Poll::process() received negative file descriptor: " + std::to_string(itr->data.fd));
194+
195+
if (static_cast<size_t>(itr->data.fd) >= m_internal->m_table.size())
196+
throw internal_error("Poll::process() received invalid file descriptor: " + std::to_string(itr->data.fd));
167197

168198
if (utils::Thread::self()->callbacks_should_interrupt_polling())
169199
utils::Thread::self()->process_callbacks(true);
170200

171201
auto evItr = m_internal->m_table.begin() + itr->data.fd;
172202

203+
if (evItr->second == nullptr) {
204+
LT_LOG_DEBUG_DATA_FD("event is null, skipping : events:%hx", itr->events);
205+
continue;
206+
}
207+
173208
// Each branch must check for data.ptr != nullptr to allow the socket
174209
// to remove itself between the calls.
175210
//
176211
// TODO: Make it so that it checks that read/write is wanted, that
177212
// it wasn't removed from one of them but not closed.
178213

179-
if (itr->events & EPOLLERR && evItr->second != nullptr && evItr->first & EPOLLERR) {
214+
if (itr->events & EPOLLERR && evItr->first & EPOLLERR) {
180215
count++;
181216
evItr->second->event_error();
217+
218+
// We assume that the event gets closed if we get an error.
219+
continue;
182220
}
183221

184-
if (itr->events & EPOLLIN && evItr->second != nullptr && evItr->first & EPOLLIN) {
222+
if (itr->events & EPOLLIN && evItr->first & EPOLLIN) {
185223
count++;
186224
evItr->second->event_read();
187225
}
188226

189-
if (itr->events & EPOLLOUT && evItr->second != nullptr && evItr->first & EPOLLOUT) {
227+
if (itr->events & EPOLLOUT && evItr->first & EPOLLOUT) {
190228
count++;
191229
evItr->second->event_write();
192230
}
@@ -203,18 +241,20 @@ Poll::open_max() const {
203241

204242
void
205243
Poll::open(Event* event) {
206-
LT_LOG_EVENT(event, DEBUG, "open event", 0);
244+
LT_LOG_EVENT("open event", 0);
207245

208-
if (m_internal->event_mask(event) != 0)
209-
throw internal_error("Poll::open(...) called but the file descriptor is active");
246+
if (m_internal->event_mask_any(event->file_descriptor()) != 0)
247+
throw internal_error("Poll::open() called but the file descriptor is active");
248+
249+
m_internal->m_table[event->file_descriptor()] = PollInternal::Table::value_type(0, event);
210250
}
211251

212252
void
213253
Poll::close(Event* event) {
214-
LT_LOG_EVENT(event, DEBUG, "close event", 0);
254+
LT_LOG_EVENT("close event", 0);
215255

216256
if (m_internal->event_mask(event) != 0)
217-
throw internal_error("Poll::close(...) called but the file descriptor is active");
257+
throw internal_error("Poll::close() called but the file descriptor is active");
218258

219259
m_internal->m_table[event->file_descriptor()] = PollInternal::Table::value_type();
220260

@@ -247,7 +287,7 @@ Poll::insert_read(Event* event) {
247287
if (m_internal->event_mask(event) & EPOLLIN)
248288
return;
249289

250-
LT_LOG_EVENT(event, DEBUG, "insert read", 0);
290+
LT_LOG_EVENT("insert read", 0);
251291

252292
m_internal->modify(event,
253293
m_internal->event_mask(event) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD,
@@ -259,7 +299,7 @@ Poll::insert_write(Event* event) {
259299
if (m_internal->event_mask(event) & EPOLLOUT)
260300
return;
261301

262-
LT_LOG_EVENT(event, DEBUG, "insert write", 0);
302+
LT_LOG_EVENT("insert write", 0);
263303

264304
m_internal->modify(event,
265305
m_internal->event_mask(event) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD,
@@ -271,7 +311,7 @@ Poll::insert_error(Event* event) {
271311
if (m_internal->event_mask(event) & EPOLLERR)
272312
return;
273313

274-
LT_LOG_EVENT(event, DEBUG, "insert error", 0);
314+
LT_LOG_EVENT("insert error", 0);
275315

276316
m_internal->modify(event,
277317
m_internal->event_mask(event) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD,
@@ -283,7 +323,7 @@ Poll::remove_read(Event* event) {
283323
if (!(m_internal->event_mask(event) & EPOLLIN))
284324
return;
285325

286-
LT_LOG_EVENT(event, DEBUG, "remove read", 0);
326+
LT_LOG_EVENT("remove read", 0);
287327

288328
uint32_t mask = m_internal->event_mask(event) & ~EPOLLIN;
289329
m_internal->modify(event,
@@ -296,7 +336,7 @@ Poll::remove_write(Event* event) {
296336
if (!(m_internal->event_mask(event) & EPOLLOUT))
297337
return;
298338

299-
LT_LOG_EVENT(event, DEBUG, "remove write", 0);
339+
LT_LOG_EVENT("remove write", 0);
300340

301341
uint32_t mask = m_internal->event_mask(event) & ~EPOLLOUT;
302342
m_internal->modify(event,
@@ -309,7 +349,7 @@ Poll::remove_error(Event* event) {
309349
if (!(m_internal->event_mask(event) & EPOLLERR))
310350
return;
311351

312-
LT_LOG_EVENT(event, DEBUG, "remove error", 0);
352+
LT_LOG_EVENT("remove error", 0);
313353

314354
uint32_t mask = m_internal->event_mask(event) & ~EPOLLERR;
315355
m_internal->modify(event,

0 commit comments

Comments
 (0)