CEF Application growing

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

CEF Application growing

Postby ccbournejr » Mon Aug 23, 2021 2:47 pm

My CEF application is causing the framework to allocate and hold memory and I was hoping I could receive some guidance as to how my CEF usage is incorrect.
When I process a GetResourceHandler request for a pdf, the framework seems to store the contents of each pdf - allocated via the stack frame below.

I'm running on Mac and I have used a differential analysis of live allocations (malloc_history) over a longer test run to isolate this call stack that is causing the memory growth. I can set a breakpoint and view that it's the PDF contents returned from my GetResourceHandler.

My build is cef_binary_92.0.21+ga9ec100+chromium-92.0.4515.107 -- any help is greatly appreciated.

Code: Select all
0   libsystem_malloc.dylib             0x7fff20479e7a _malloc_zone_malloc + 242
1   org.chromium.ContentShell.framework        0x10d3754f8 operator new(unsigned long) + 40  new.cpp:67
2   org.chromium.ContentShell.framework        0x10ab71e1f std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >::__append(unsigned long) + 111  vector:1093
3   org.chromium.ContentShell.framework        0x1101b9cf9 storage::BlobDataItem::AllocateBytes() + 41  blob_data_item.cc:181
4   org.chromium.ContentShell.framework        0x1101b46dc storage::BlobBuilderFromStream::WritePipeToFutureDataHelper::Populate(base::span<char const, 18446744073709551615ul>, unsigned long long) + 44  blob_builder_from_stream.cc:299
5   org.chromium.ContentShell.framework        0x1101b4866 storage::(anonymous namespace)::DataPipeConsumerHelper::DataPipeReady(unsigned int, mojo::HandleSignalsState const&) + 182  blob_builder_from_stream.cc:108
6   org.chromium.ContentShell.framework        0x10d90718e mojo::SimpleWatcher::OnHandleReady(int, unsigned int, mojo::HandleSignalsState const&) + 286  simple_watcher.cc:279
7   org.chromium.ContentShell.framework        0x10d741513 base::TaskAnnotator::RunTask(char const*, base::PendingTask*) + 323  task_annotator.cc:178
8   org.chromium.ContentShell.framework        0x10d755a9f base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::sequence_manager::LazyNow*) + 415  thread_controller_with_message_pump_impl.cc:361
9   org.chromium.ContentShell.framework        0x10d7557bb base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() + 107  thread_controller_with_message_pump_impl.cc:260
10  org.chromium.ContentShell.framework        0x10d755ea2 non-virtual thunk to base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() + 18  thread_controller_with_message_pump_impl.cc:0
11  org.chromium.ContentShell.framework        0x10d7bd307 base::MessagePumpKqueue::Run(base::MessagePump::Delegate*) + 151  message_pump_kqueue.cc:173
12  org.chromium.ContentShell.framework        0x10d7560e0 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 208  thread_controller_with_message_pump_impl.cc:471
13  org.chromium.ContentShell.framework        0x10d7205db base::RunLoop::Run(base::Location const&) + 411  run_loop.cc:136
14  org.chromium.ContentShell.framework        0x10d771938 base::Thread::Run(base::RunLoop*) + 56  thread.cc:326
15  org.chromium.ContentShell.framework        0x10bc8d190 content::BrowserProcessIOThread::IOThreadRun(base::RunLoop*) + 96  browser_process_io_thread.cc:131
16  org.chromium.ContentShell.framework        0x10d771ac8 base::Thread::ThreadMain() + 376  thread.cc:399
17  org.chromium.ContentShell.framework        0x10d790a48 base::(anonymous namespace)::ThreadFunc(void*) + 104  platform_thread_posix.cc:98
18  libsystem_pthread.dylib            0x7fff20639950 _pthread_start + 224
19  libsystem_pthread.dylib            0x7fff2063547b thread_start + 15
ccbournejr
Techie
 
Posts: 30
Joined: Mon Aug 23, 2021 7:47 am

Re: CEF Application growing

Postby magreenblatt » Mon Aug 23, 2021 3:17 pm

When I process a GetResourceHandler request for a pdf

How, specifically, are you doing that? Please show code.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: CEF Application growing

Postby ccbournejr » Tue Aug 24, 2021 9:42 am

The PDF is a fetch request from js. We intercept the http request and use the cef class to create a resource handler
I’ve included some of the code from our CefResourceRequestHandler that composes the CefResourceHandler return (below)

Code: Select all
CefRefPtr<CefResourceHandler> RequestHandler::GetResourceHandler(CefRefPtr<CefBrowser> browser,
                                                                          CefRefPtr<CefFrame> frame,
                                                                          CefRefPtr<CefRequest> request)
{
    /* .. decisions related to where the content lives */
    /* .. in our test case the file is in the local file system */   

    unsigned char* fileData;
    size_t size;
    std::string filePath;

    /* .. the local pdf is recovered into fileData successfully */
    /* .. filePath   std::string   "/Library/Application Support/SampleApp/.media//ip-118715089622362213309.pdf”   */
    /* .. size   size_t   20702285 */
    /* .. fileData   unsigned char *   "%PDF-1.4..” */

    CefRefPtr<CefResourceHandler> resourceHandler;
    resourceHandler = GetStreamResourceHandlerForData(filePath, fileData, size);

    return resoureceHandler;
}

CefRefPtr<CefResourceHandler> RequestHandler::GetStreamResourceHandlerForData(string filePath, unsigned char* fileData, size_t size)
{
  CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(static_cast<void*>(fileData), size);

  multimap<CefString, CefString> headerMap;
  CefResponse::HeaderMap::value_type data(CefString("Access-Control-Allow-Origin"), CefString("*"));
  headerMap.insert(data);

  string mimeType = this->getMIMEType(filePath);
  /* mimeType   std::string   "application/pdf”   */

  return new CefStreamResourceHandler(200, "Ok", mimeType, headerMap, stream);
}
ccbournejr
Techie
 
Posts: 30
Joined: Mon Aug 23, 2021 7:47 am

Re: CEF Application growing

Postby magreenblatt » Tue Aug 24, 2021 10:07 am

How are you loading |fileData|? What frees that memory? CefStreamReader will copy it, not take ownership.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: CEF Application growing

Postby ccbournejr » Tue Aug 24, 2021 11:50 am

Sorry, yea that memory is deleted via a:
delete [] fileData;

The interesting aspect is that the call stack that is appearing to grow does not have any of our software in the stack frame on the IO Thread.
I am struggling to understand why that code allocates memory and it wouldn't be released.

Thanks for any and all help/suggestions.
ccbournejr
Techie
 
Posts: 30
Joined: Mon Aug 23, 2021 7:47 am

Re: CEF Application growing

Postby ccbournejr » Thu Aug 26, 2021 2:31 pm

Small update: I made a simple app that requests and returns an "application/ogg". For a simple javascript that drops the returned data after creating a blob -- I cannot reproduce my issue. But, if intentionally create a leak on the javascript consumer, the main process grows along with my Renderer process. Which, I didn't expect.

Code: Select all
    const blob = [];
    async function loadForever() {
        for (let i = 0; i < 100000; i++) {
            $.ajax("junkity", {
               headers: { 'custom-header': 'custom-header-value'},
               type: 'GET',
               contentType: 'application/ogg'
            }).done(function (data) {
               blob[i] = new Blob([data], { type: 'application/ogg' });
               var link = window.document.createElement('a');
               link.href = window.URL.createObjectURL(blob[i]);
               link.download = '';
               link.click();
            });
            await new Promise(r => setTimeout(r, 5000));
        }
    }
ccbournejr
Techie
 
Posts: 30
Joined: Mon Aug 23, 2021 7:47 am

Re: CEF Application growing

Postby ccbournejr » Thu Sep 09, 2021 12:43 pm

Problem solved - Just a final update. I fixed the leaks of blobs in my application on the javascript side and the main process released all the blobs held.
ccbournejr
Techie
 
Posts: 30
Joined: Mon Aug 23, 2021 7:47 am


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 37 guests