Merge pull request #75 from oatpp/fix_memory_leak_IOEventWorker_kqueue

unique_ptr for IOEventWorker::m_inEvents
This commit is contained in:
Leonid Stryzhevskyi 2019-05-22 01:37:24 +03:00 committed by GitHub
commit 1a638cec83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 14 deletions

View File

@ -75,9 +75,10 @@ private:
private:
oatpp::data::v_io_handle m_eventQueueHandle;
oatpp::data::v_io_handle m_wakeupTrigger;
p_char8 m_inEvents;
std::unique_ptr<v_char8[]> m_inEvents;
v_int32 m_inEventsCount;
p_char8 m_outEvents;
v_int32 m_inEventsCapacity;
std::unique_ptr<v_char8[]> m_outEvents;
private:
std::thread m_thread;
private:

View File

@ -40,6 +40,7 @@ IOEventWorker::IOEventWorker(IOEventWorkerForeman* foreman, Action::IOEventType
, m_wakeupTrigger(-1)
, m_inEvents(nullptr)
, m_inEventsCount(0)
, m_inEventsCapacity(0)
, m_outEvents(nullptr)
{
m_thread = std::thread(&IOEventWorker::run, this);
@ -47,9 +48,6 @@ IOEventWorker::IOEventWorker(IOEventWorkerForeman* foreman, Action::IOEventType
IOEventWorker::~IOEventWorker() {
delete[] m_inEvents;
delete[] m_outEvents;
if(m_eventQueueHandle >=0) {
::close(m_eventQueueHandle);
}

View File

@ -46,7 +46,13 @@ void IOEventWorker::initEventQueue() {
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Call to ::epoll_create1() failed.");
}
m_outEvents = (p_char8)(new struct epoll_event[MAX_EVENTS]);
m_outEvents = std::unique_ptr<v_char8[]>(new (std::nothrow) v_char8[MAX_EVENTS * sizeof(struct epoll_event)]);
if(!m_outEvents) {
OATPP_LOGD("[oatpp::async::worker::IOEventWorker::initEventQueue()]",
"Error. Unable to allocate %d bytes for events.", MAX_EVENTS * sizeof(struct epoll_event));
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Unable to allocate memory for events.");
}
m_wakeupTrigger = ::eventfd(0, EFD_NONBLOCK);
@ -143,7 +149,8 @@ void IOEventWorker::consumeBacklog() {
void IOEventWorker::waitEvents() {
auto eventsCount = epoll_wait(m_eventQueueHandle, (struct epoll_event*)m_outEvents, MAX_EVENTS, -1);
struct epoll_event* outEvents = (struct epoll_event*)m_outEvents.get();
auto eventsCount = epoll_wait(m_eventQueueHandle, outEvents, MAX_EVENTS, -1);
if(eventsCount < 0) {
OATPP_LOGD("[oatpp::async::worker::IOEventWorker::waitEvents()]", "Error. errno=%d", errno);
@ -154,8 +161,7 @@ void IOEventWorker::waitEvents() {
for(v_int32 i = 0; i < eventsCount; i ++) {
struct epoll_event* event = (struct epoll_event*)&m_outEvents[i * sizeof(struct epoll_event)];
void* dataPtr = event->data.ptr;
void* dataPtr = outEvents[i].data.ptr;
if(dataPtr != nullptr) {

View File

@ -43,7 +43,12 @@ void IOEventWorker::initEventQueue() {
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Call to ::kqueue() failed.");
}
m_outEvents = (p_char8)(new struct kevent[MAX_EVENTS]);
m_outEvents = std::unique_ptr<v_char8[]>(new (std::nothrow) v_char8[MAX_EVENTS * sizeof(struct kevent)]);
if(!m_outEvents) {
OATPP_LOGD("[oatpp::async::worker::IOEventWorker::initEventQueue()]",
"Error. Unable to allocate %d bytes for events.", MAX_EVENTS * sizeof(struct kevent));
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Unable to allocate memory for events.");
}
}
@ -118,15 +123,26 @@ void IOEventWorker::consumeBacklog() {
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_backlogLock);
m_inEventsCount = m_backlog.count + 1;
m_inEvents = (p_char8)(new struct kevent[m_inEventsCount]);
v_int32 eventSize = sizeof(struct kevent);
if(m_inEventsCapacity < m_inEventsCount) {
m_inEventsCapacity = m_inEventsCount;
m_inEvents = std::unique_ptr<v_char8[]>(new (std::nothrow) v_char8[m_inEventsCapacity * sizeof(struct kevent)]);
if(!m_inEvents) {
OATPP_LOGD("[oatpp::async::worker::IOEventWorker::consumeBacklog()]",
"Error. Unable to allocate %d bytes for events.", m_inEventsCapacity * sizeof(struct kevent));
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::consumeBacklog()]: Error. Unable to allocate memory for events.");
}
}
setTriggerEvent(&m_inEvents[0]);
auto curr = m_backlog.first;
v_int32 i = 1;
while(curr != nullptr) {
setCoroutineEvent(curr, 0, &m_inEvents[i * eventSize]);
setCoroutineEvent(curr, 0, &m_inEvents[i * sizeof(struct kevent)]);
curr = nextCoroutine(curr);
++i;
}
@ -139,7 +155,7 @@ void IOEventWorker::consumeBacklog() {
void IOEventWorker::waitEvents() {
auto eventsCount = kevent(m_eventQueueHandle, (struct kevent*)m_inEvents, m_inEventsCount, (struct kevent*)m_outEvents, MAX_EVENTS, NULL);
auto eventsCount = kevent(m_eventQueueHandle, (struct kevent*)m_inEvents.get(), m_inEventsCount, (struct kevent*)m_outEvents.get(), MAX_EVENTS, NULL);
if(eventsCount < 0) {
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Event loop failed.");