Skip to content

Commit ddd816a

Browse files
committed
CEF memory leaks #1
1 parent 20a14e8 commit ddd816a

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

Client/cefweb/CAjaxResourceHandler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@ void CAjaxResourceHandler::SetResponse(const SString& data)
3434
m_bHasData = true;
3535

3636
if (m_callback)
37+
{
3738
m_callback->Continue();
39+
// Release callback to prevent memory leak
40+
m_callback = nullptr;
41+
}
3842
}
3943

4044
// CefResourceHandler implementation
4145
void CAjaxResourceHandler::Cancel()
4246
{
47+
// Release callback reference on cancellation to prevent memory leak
48+
m_callback = nullptr;
4349
}
4450

4551
void CAjaxResourceHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64& response_length, CefString& redirectUrl)

Client/cefweb/CWebCore.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,18 @@ void CWebCore::AddEventToEventQueue(std::function<void()> event, CWebView* pWebV
164164

165165
std::lock_guard<std::mutex> lock(m_EventQueueMutex);
166166

167+
// Prevent unbounded queue growth - drop oldest events if queue is too large
168+
if (m_EventQueue.size() >= MAX_EVENT_QUEUE_SIZE)
169+
{
170+
// Log warning even in release builds as this indicates a serious issue
171+
g_pCore->GetConsole()->Printf("WARNING: Browser event queue size limit reached (%d), dropping oldest events", MAX_EVENT_QUEUE_SIZE);
172+
173+
// Remove oldest 10% of events to make room
174+
auto removeCount = MAX_EVENT_QUEUE_SIZE / 10;
175+
for (size_t i = 0; i < removeCount && !m_EventQueue.empty(); ++i)
176+
m_EventQueue.pop_front();
177+
}
178+
167179
#ifndef MTA_DEBUG
168180
m_EventQueue.push_back(EventEntry(event, pWebView));
169181
#else
@@ -215,6 +227,22 @@ void CWebCore::WaitForTask(std::function<void(bool)> task, CWebView* webView)
215227
std::future<void> result;
216228
{
217229
std::scoped_lock lock(m_TaskQueueMutex);
230+
231+
// Prevent unbounded queue growth - if queue is too large, oldest tasks will be dropped during pulse
232+
if (m_TaskQueue.size() >= MAX_TASK_QUEUE_SIZE)
233+
{
234+
#ifdef MTA_DEBUG
235+
g_pCore->GetConsole()->Printf("Warning: Task queue size limit reached (%d), task will be aborted", MAX_TASK_QUEUE_SIZE);
236+
#endif
237+
// Must still queue the task to fulfill the future, but it will be aborted during processing
238+
// Removing oldest task to make room
239+
if (!m_TaskQueue.empty())
240+
{
241+
m_TaskQueue.front().task(true); // Abort oldest task
242+
m_TaskQueue.pop_front();
243+
}
244+
}
245+
218246
m_TaskQueue.emplace_back(TaskEntry{task, webView});
219247
result = m_TaskQueue.back().task.get_future();
220248
}
@@ -358,13 +386,39 @@ void CWebCore::AddAllowedPage(const SString& strURL, eWebFilterType filterType)
358386
{
359387
std::lock_guard<std::recursive_mutex> lock(m_FilterMutex);
360388

389+
// Prevent unbounded whitelist growth - remove old REQUEST entries if limit reached
390+
if (m_Whitelist.size() >= MAX_WHITELIST_SIZE)
391+
{
392+
// Remove WEBFILTER_REQUEST entries (temporary session entries)
393+
for (auto iter = m_Whitelist.begin(); iter != m_Whitelist.end();)
394+
{
395+
if (iter->second.second == eWebFilterType::WEBFILTER_REQUEST)
396+
m_Whitelist.erase(iter++);
397+
else
398+
++iter;
399+
}
400+
}
401+
361402
m_Whitelist[strURL] = std::pair<bool, eWebFilterType>(true, filterType);
362403
}
363404

364405
void CWebCore::AddBlockedPage(const SString& strURL, eWebFilterType filterType)
365406
{
366407
std::lock_guard<std::recursive_mutex> lock(m_FilterMutex);
367408

409+
// Prevent unbounded whitelist growth - remove old REQUEST entries if limit reached
410+
if (m_Whitelist.size() >= MAX_WHITELIST_SIZE)
411+
{
412+
// Remove WEBFILTER_REQUEST entries (temporary session entries)
413+
for (auto iter = m_Whitelist.begin(); iter != m_Whitelist.end();)
414+
{
415+
if (iter->second.second == eWebFilterType::WEBFILTER_REQUEST)
416+
m_Whitelist.erase(iter++);
417+
else
418+
++iter;
419+
}
420+
}
421+
368422
m_Whitelist[strURL] = std::pair<bool, eWebFilterType>(false, filterType);
369423
}
370424

Client/cefweb/CWebCore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#define MTA_BROWSERDATA_PATH "mta/cef/browserdata.xml"
2121
#define BROWSER_LIST_UPDATE_INTERVAL (24*60*60)
2222
#define BROWSER_UPDATE_URL "https://cef.multitheftauto.com/get.php"
23+
#define MAX_EVENT_QUEUE_SIZE 10000
24+
#define MAX_TASK_QUEUE_SIZE 1000
25+
#define MAX_WHITELIST_SIZE 50000
2326
#define GetNextSibling(hwnd) GetWindow(hwnd, GW_HWNDNEXT) // Re-define the conflicting macro
2427
#define GetFirstChild(hwnd) GetTopWindow(hwnd)
2528

Client/cefweb/CWebView.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ CWebView::~CWebView()
4444
// Make sure we don't dead lock the CEF render thread
4545
ResumeCefThread();
4646

47+
// Clean up AJAX handlers to prevent accumulation
48+
m_AjaxHandlers.clear();
49+
4750
// Ensure that CefRefPtr::~CefRefPtr doesn't try to release it twice (it has already been released in CWebView::OnBeforeClose)
4851
m_pWebView = nullptr;
4952

@@ -719,6 +722,8 @@ void CWebView::OnPaint(CefRefPtr<CefBrowser> browser, CefRenderHandler::PaintEle
719722
m_RenderData.width = width;
720723
m_RenderData.height = height;
721724
m_RenderData.dirtyRects = dirtyRects;
725+
// Prevent vector capacity growth memory leak - shrink excess capacity
726+
m_RenderData.dirtyRects.shrink_to_fit();
722727
m_RenderData.changed = true;
723728

724729
// Wait for the main thread to handle drawing the texture

0 commit comments

Comments
 (0)