From 8cd13833d986247ecd8a9799d8804621e9e7f704 Mon Sep 17 00:00:00 2001 From: BotoX Date: Tue, 18 Jun 2019 22:21:30 +0200 Subject: [PATCH] Fix multithreaded loop clean-up, fixes #888 (#902) * Fix multithreaded loop clean-up, fixes #888 * Style fixes --- src/Loop.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Loop.h b/src/Loop.h index 918520d..b2793fc 100644 --- a/src/Loop.h +++ b/src/Loop.h @@ -80,26 +80,35 @@ private: return ((Loop *) us_create_loop(hint, wakeupCb, preCb, postCb, sizeof(LoopData)))->init(); } + /* What to do with loops created with existingNativeLoop? */ + struct LoopCleaner { + ~LoopCleaner() { + if(loop && cleanMe) { + loop->free(); + } + } + Loop *loop = nullptr; + bool cleanMe = false; + }; + public: /* Lazily initializes a per-thread loop and returns it. * Will automatically free all initialized loops at exit. */ static Loop *get(void *existingNativeLoop = nullptr) { - static thread_local Loop *lazyLoop; - if (!lazyLoop) { + static thread_local LoopCleaner lazyLoop; + if (!lazyLoop.loop) { /* If we are given a native loop pointer we pass that to uSockets and let it deal with it */ if (existingNativeLoop) { /* Todo: here we want to pass the pointer, not a boolean */ - lazyLoop = create(existingNativeLoop); + lazyLoop.loop = create(existingNativeLoop); /* We cannot register automatic free here, must be manually done */ } else { - lazyLoop = create(nullptr); - std::atexit([]() { - Loop::get()->free(); - }); + lazyLoop.loop = create(nullptr); + lazyLoop.cleanMe = true; } } - return lazyLoop; + return lazyLoop.loop; } /* Freeing the default loop should be done once */