Browse Source

Fix (mostly false-positive) memory leaks in task dispatching

Ivan Savenko 6 months ago
parent
commit
3547635c05
2 changed files with 16 additions and 5 deletions
  1. 13 5
      client/eventsSDL/InputHandler.cpp
  2. 3 0
      client/eventsSDL/InputHandler.h

+ 13 - 5
client/eventsSDL/InputHandler.cpp

@@ -405,23 +405,31 @@ int InputHandler::getNumTouchFingers() const
 
 void InputHandler::dispatchMainThread(const std::function<void()> & functor)
 {
-	auto heapFunctor = new std::function<void()>(functor);
+	auto heapFunctor = std::make_unique<std::function<void()>>(functor);
 
 	SDL_Event event;
 	event.user.type = SDL_USEREVENT;
 	event.user.code = 0;
-	event.user.data1 = static_cast <void*>(heapFunctor);
+	event.user.data1 = static_cast <void*>(heapFunctor.get());
 	event.user.data2 = nullptr;
 	SDL_PushEvent(&event);
+
+	// NOTE: approach with dispatchedTasks container is a bit excessive
+	// used mostly to prevent false-positives leaks in analyzers
+	dispatchedTasks.push(std::move(heapFunctor));
 }
 
 void InputHandler::handleUserEvent(const SDL_UserEvent & current)
 {
-	auto heapFunctor = static_cast<std::function<void()>*>(current.data1);
+	std::unique_ptr<std::function<void()>> task;
+
+	if (!dispatchedTasks.try_pop(task))
+		throw std::runtime_error("InputHandler::handleUserEvent received without active task!");
 
-	(*heapFunctor)();
+	if (current.data1 != task.get())
+		throw std::runtime_error("InputHandler::handleUserEvent received unknown pointer!");
 
-	delete heapFunctor;
+	(*task)();
 }
 
 const Point & InputHandler::getCursorPosition() const

+ 3 - 0
client/eventsSDL/InputHandler.h

@@ -12,6 +12,8 @@
 
 #include "../lib/Rect.h"
 
+#include <tbb/concurrent_queue.h>
+
 enum class EUserEvent;
 enum class MouseButton;
 union SDL_Event;
@@ -33,6 +35,7 @@ enum class InputMode
 class InputHandler
 {
 	std::vector<SDL_Event> eventsQueue;
+	tbb::concurrent_queue<std::unique_ptr<std::function<void()>>> dispatchedTasks;
 	std::mutex eventsMutex;
 
 	Point cursorPosition;