From ab83f51735d21dde77aa5f946cde3b0266997e44 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 14 Mar 2019 09:19:30 -0400 Subject: [PATCH 1/2] clear errno --- llarp/ev/ev_epoll.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llarp/ev/ev_epoll.cpp b/llarp/ev/ev_epoll.cpp index adcabe097..def589aa3 100644 --- a/llarp/ev/ev_epoll.cpp +++ b/llarp/ev/ev_epoll.cpp @@ -343,7 +343,6 @@ llarp_epoll_loop::tick(int ms) { llarp::LogDebug("epoll error"); ev->error(); - errno = 0; } else { @@ -362,12 +361,13 @@ llarp_epoll_loop::tick(int ms) } } ++idx; + // clear errno just in case + errno = 0; } } if(result != -1) tick_listeners(); /// if we didn't get an io events we sleep to avoid 100% cpu use - errno = 0; if(!didIO) std::this_thread::sleep_for(std::chrono::milliseconds(ms)); return result; From 8d078f19eb9527622f5d060c260fba1a42059e2b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 15 Mar 2019 10:31:54 -0400 Subject: [PATCH 2/2] wrap epoll with IO checks for resetting errno --- llarp/ev/ev.cpp | 13 ++++++------- llarp/ev/ev.hpp | 21 +++++++++++++++++++++ llarp/ev/ev_epoll.cpp | 25 ++++++++++++++++--------- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/llarp/ev/ev.cpp b/llarp/ev/ev.cpp index 556f3b72e..8e51ff213 100644 --- a/llarp/ev/ev.cpp +++ b/llarp/ev/ev.cpp @@ -51,8 +51,7 @@ llarp_make_ev_loop() #error no event loop subclass #endif r->init(); - r->_now = llarp::time_now_ms(); - + r->update_time(); return r; } @@ -71,7 +70,7 @@ llarp_ev_loop_run(struct llarp_ev_loop *ev, llarp::Logic *logic) { while(ev->running()) { - ev->_now = llarp::time_now_ms(); + ev->update_time(); ev->tick(EV_TICK_INTERVAL); if(ev->running()) logic->tick(ev->_now); @@ -92,12 +91,12 @@ llarp_ev_loop_run_single_process(struct llarp_ev_loop *ev, { while(ev->running()) { - ev->_now = llarp::time_now_ms(); + ev->update_time(); ev->tick(EV_TICK_INTERVAL); if(ev->running()) { - ev->_now = llarp::time_now_ms(); - logic->tick_async(ev->_now); + ev->update_time(); + logic->tick_async(ev->time_now()); llarp_threadpool_tick(tp); } } @@ -125,7 +124,7 @@ llarp_time_t llarp_ev_loop_time_now_ms(struct llarp_ev_loop *loop) { if(loop) - return loop->_now; + return loop->time_now(); return llarp::time_now_ms(); } diff --git a/llarp/ev/ev.hpp b/llarp/ev/ev.hpp index a18cd7801..ff54dd683 100644 --- a/llarp/ev/ev.hpp +++ b/llarp/ev/ev.hpp @@ -50,6 +50,15 @@ typedef struct sockaddr_un #define EV_WRITE_BUF_SZ (2 * 1024UL) #endif +/// do io and reset errno after +static ssize_t +IO(std::function< ssize_t(void) > iofunc) +{ + ssize_t ret = iofunc(); + errno = 0; + return ret; +} + namespace llarp { #ifdef _WIN32 @@ -697,6 +706,18 @@ struct llarp_ev_loop virtual bool running() const = 0; + void + update_time() + { + _now = llarp::time_now_ms(); + } + + virtual llarp_time_t + time_now() const + { + return _now; + } + /// return false on socket error (non blocking) virtual bool tcp_connect(llarp_tcp_connecter* tcp, const sockaddr* addr) = 0; diff --git a/llarp/ev/ev_epoll.cpp b/llarp/ev/ev_epoll.cpp index def589aa3..1b9baaed0 100644 --- a/llarp/ev/ev_epoll.cpp +++ b/llarp/ev/ev_epoll.cpp @@ -341,35 +341,42 @@ llarp_epoll_loop::tick(int ms) " events=", std::to_string(events[idx].events)); if(events[idx].events & EPOLLERR && errno) { - llarp::LogDebug("epoll error"); - ev->error(); + IO([&]() -> ssize_t { + llarp::LogDebug("epoll error"); + ev->error(); + return 0; + }); } else { // write THEN READ don't revert me if(events[idx].events & EPOLLOUT) { - llarp::LogDebug("epoll out"); - ev->flush_write(); + IO([&]() -> ssize_t { + llarp::LogDebug("epoll out"); + ev->flush_write(); + return 0; + }); } if(events[idx].events & EPOLLIN) { - llarp::LogDebug("epoll in"); - if(ev->read(readbuf, sizeof(readbuf)) > 0) + ssize_t amount = IO([&]() -> ssize_t { + llarp::LogDebug("epoll in"); + return ev->read(readbuf, sizeof(readbuf)); + }); + if(amount > 0) didIO = true; } } } ++idx; - // clear errno just in case - errno = 0; } } if(result != -1) tick_listeners(); /// if we didn't get an io events we sleep to avoid 100% cpu use if(!didIO) - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); return result; }