diff --git a/emper/ContextManager.cpp b/emper/ContextManager.cpp index 88a651c86856d27a0b36ecfb895d08e5cf7d06bf..7a15eb4b6002bea2e095ff0a0d963284b20bdc2e 100644 --- a/emper/ContextManager.cpp +++ b/emper/ContextManager.cpp @@ -64,5 +64,17 @@ void ContextManager::discardAndResume(Context* context) { LOGD("Freeing context " << contextToFree); putFreeContext(contextToFree); }); + + // Since we are going to discard this context, it will never reach + // the end of its dispatch loop, and hence we need to ensure that + // the fiber is recycled. + const Fiber* currentFiber = Dispatcher::currentFiber; + if (currentFiber) { + Dispatcher::recycle(currentFiber); + + // Set currentFiber to nullptr to avoid double frees here. + Dispatcher::currentFiber = nullptr; + } + contextToFree->discardAndResume(context); } diff --git a/emper/ContextManager.hpp b/emper/ContextManager.hpp index e39f5b32930c6732c314f1b2059a68ba3603e70c..35cbfc8757cf803e9182510516660300d7c266f2 100644 --- a/emper/ContextManager.hpp +++ b/emper/ContextManager.hpp @@ -1,6 +1,7 @@ #pragma once #include "Common.hpp" +#include "Dispatcher.hpp" #include "WsClQueue.hpp" #include "Runtime.hpp" #include "Context.hpp" @@ -17,6 +18,8 @@ private: friend Context; + friend Dispatcher; + public: ContextManager(Runtime& runtime); diff --git a/emper/Dispatcher.hpp b/emper/Dispatcher.hpp index 16a6b8846e3b0bcf32d709caa4545b40da0b35a5..f7b8d11799419e11d03144dd67a2fd060761cbed 100644 --- a/emper/Dispatcher.hpp +++ b/emper/Dispatcher.hpp @@ -35,7 +35,7 @@ protected: return fiber->doAtomicDecrRefCount(); } - inline void recycle(const Fiber* fiber) { + static inline void recycle(const Fiber* fiber) { delete fiber; }