Commit 3372195e authored by Dominik Charousset's avatar Dominik Charousset

fixed issue EPOLL_CTL_DEL issue, relates #77

parent 1191a328
...@@ -934,19 +934,19 @@ class event_loop_impl : public middleman_listener { ...@@ -934,19 +934,19 @@ class event_loop_impl : public middleman_listener {
} }
// operation: EPOLL_CTL_ADD or EPOLL_CTL_DEL // operation: EPOLL_CTL_ADD or EPOLL_CTL_DEL
// fd_op: optional if operation is EPOLL_CTL_DEL, otherwise EPOLLIN or EPOLLOUT // fd_op: EPOLLIN, EPOLLOUT or (EPOLLIN | EPOLLOUT)
template<typename T = void> template<typename T = void>
bool epoll_op(int operation, int fd, T* ptr = nullptr, int fd_op = 0) { void epoll_op(int operation, int fd, int fd_op, T* ptr = nullptr) {
CPPA_REQUIRE(operation == EPOLL_CTL_ADD || operation == EPOLL_CTL_DEL); CPPA_REQUIRE(operation == EPOLL_CTL_ADD || operation == EPOLL_CTL_DEL);
CPPA_REQUIRE(operation == EPOLL_CTL_DEL || ptr != nullptr); CPPA_REQUIRE(operation == EPOLL_CTL_DEL || ptr != nullptr);
CPPA_REQUIRE(operation == EPOLL_CTL_DEL || (fd_op == EPOLLIN || fd_op == EPOLLOUT)); CPPA_REQUIRE(fd_op == EPOLLIN || fd_op == EPOLLOUT || fd_op == (EPOLLIN | EPOLLOUT));
// make sure T has correct type // make sure T has correct type
CPPA_REQUIRE( (fd_op == 0 ) CPPA_REQUIRE( (operation == EPOLL_CTL_DEL && is_same<T,void>::value)
|| (fd_op == EPOLLIN && is_same<T,network_channel>::value) || ((fd_op & EPOLLIN) && is_same<T,network_channel>::value)
|| (fd_op == EPOLLOUT && is_same<T,peer_connection>::value)); || (fd_op == EPOLLOUT && is_same<T,peer_connection>::value));
epoll_event ee; epoll_event ee;
// also fire event on peer shutdown on input operations // also fire event on peer shutdown on input operations
ee.events = (fd_op == EPOLLIN) ? (fd_op | EPOLLRDHUP) : fd_op; ee.events = (fd_op & EPOLLIN) ? (fd_op | EPOLLRDHUP) : fd_op;
// always store peer_connection_ptr, because we don't have full type information // always store peer_connection_ptr, because we don't have full type information
// in case of epoll_wait error otherwise // in case of epoll_wait error otherwise
ee.data.ptr = static_cast<peer_connection*>(ptr); ee.data.ptr = static_cast<peer_connection*>(ptr);
...@@ -977,7 +977,7 @@ class event_loop_impl : public middleman_listener { ...@@ -977,7 +977,7 @@ class event_loop_impl : public middleman_listener {
} }
else if (operation == EPOLL_CTL_DEL) { else if (operation == EPOLL_CTL_DEL) {
// nothing to delete here // nothing to delete here
cerr << "*** warning: tried to delete unknown file descriptor" << endl; return;
} }
else { // operation == EPOLL_CTL_ADD else { // operation == EPOLL_CTL_ADD
CPPA_REQUIRE(operation == EPOLL_CTL_ADD); CPPA_REQUIRE(operation == EPOLL_CTL_ADD);
...@@ -1032,13 +1032,11 @@ class event_loop_impl : public middleman_listener { ...@@ -1032,13 +1032,11 @@ class event_loop_impl : public middleman_listener {
break; break;
} }
} }
return false; // tell client operation had no effect
} }
return true;
} }
void channel_added(const network_channel_ptr& ptr) { void channel_added(const network_channel_ptr& ptr) {
epoll_op(EPOLL_CTL_ADD, ptr->read_handle(), ptr.get(), EPOLLIN); epoll_op(EPOLL_CTL_ADD, ptr->read_handle(), EPOLLIN, ptr.get());
} }
void channel_erased(const network_channel_ptr& ptr) { void channel_erased(const network_channel_ptr& ptr) {
...@@ -1046,7 +1044,7 @@ class event_loop_impl : public middleman_listener { ...@@ -1046,7 +1044,7 @@ class event_loop_impl : public middleman_listener {
} }
void continue_writing_later(const peer_connection_ptr& ptr) { void continue_writing_later(const peer_connection_ptr& ptr) {
epoll_op(EPOLL_CTL_ADD, ptr->write_handle(), ptr.get(), EPOLLOUT); epoll_op(EPOLL_CTL_ADD, ptr->write_handle(), EPOLLOUT, ptr.get());
} }
template<typename F> template<typename F>
...@@ -1118,18 +1116,14 @@ class event_loop_impl : public middleman_listener { ...@@ -1118,18 +1116,14 @@ class event_loop_impl : public middleman_listener {
if (e.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) { if (e.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) {
auto ptr = reinterpret_cast<network_channel*>(e.data.ptr); auto ptr = reinterpret_cast<network_channel*>(e.data.ptr);
// see you later! // see you later!
epoll_op(EPOLL_CTL_DEL, ptr->read_handle()); m_marked_inputs.push_back(ptr);
// remove write handle as well if possible, since we don't
// support read-only connections anyways
auto wptr = dynamic_cast<peer_connection*>(ptr);
if (wptr) epoll_op(EPOLL_CTL_DEL, wptr->write_handle());
} }
else { else {
// can be both! // can be both!
if (e.events & EPOLLIN) { if (e.events & EPOLLIN) {
auto ptr = reinterpret_cast<network_channel*>(e.data.ptr); auto ptr = reinterpret_cast<network_channel*>(e.data.ptr);
if (!proceed([ptr] { return ptr->continue_reading(); })) { if (!proceed([ptr] { return ptr->continue_reading(); })) {
epoll_op(EPOLL_CTL_DEL, ptr->read_handle()); epoll_op(EPOLL_CTL_DEL, ptr->read_handle(), EPOLLIN);
} }
} }
if (e.events & EPOLLOUT) { if (e.events & EPOLLOUT) {
...@@ -1138,17 +1132,23 @@ class event_loop_impl : public middleman_listener { ...@@ -1138,17 +1132,23 @@ class event_loop_impl : public middleman_listener {
// to register network_channel pointers with EPOLLOUT // to register network_channel pointers with EPOLLOUT
auto ptr = static_cast<peer_connection*>(bptr); auto ptr = static_cast<peer_connection*>(bptr);
if (!proceed([ptr] { return ptr->continue_writing(); })) { if (!proceed([ptr] { return ptr->continue_writing(); })) {
epoll_op(EPOLL_CTL_DEL, ptr->write_handle()); epoll_op(EPOLL_CTL_DEL, ptr->write_handle(), EPOLLOUT);
} }
} }
} }
} }
// sweep marked pointers // sweep marked pointers
for (auto& ptr : m_marked_inputs) { for (auto& ptr : m_marked_inputs) {
epoll_op(EPOLL_CTL_DEL, ptr->read_handle()); auto fd = ptr->read_handle();
// remove write handle as well if needed epoll_op(EPOLL_CTL_DEL, fd, EPOLLIN | EPOLLOUT);
// remove write handle as well if possible, since we don't
// support read-only connections anyways
auto wptr = dynamic_cast<peer_connection*>(ptr.get()); auto wptr = dynamic_cast<peer_connection*>(ptr.get());
if (wptr) epoll_op(EPOLL_CTL_DEL, wptr->write_handle()); if (wptr) {
auto wfd = wptr->write_handle();
if (fd != wfd) epoll_op(EPOLL_CTL_DEL, wfd, EPOLLOUT);
// else: already deleted
}
} }
// cleanup // cleanup
m_marked_inputs.clear(); m_marked_inputs.clear();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment