magreenblatt wrote:Is it possible that your app is not calling CefShutdown in all cases (perhaps exiting early with exit() or similar)? Does the problem reproduce with 'cefclient --external-message-pump'? Are you implementing CefDoMessageLoopWork as shown in cefclient?
Mikael wrote:In the process of testing out PR 158 we upgraded from 3.3112.1650 to 3.3325.1752 and we've had this issue appear very frequently since then.
Basically, when stopping a debugging session (thereby killing the browser process being debugged) in Visual Studio, or for some other reason not cleanly exiting with a CefShutdown (like an exit(0)), you often get a renderer process that's just hanging around and consumes one virtual CPU core as it's constantly retrying the task RenderWidgetCompositor::RequestNewLayerTreeFrameSink.
I was under the assumption that this stemmed from changes related to the PR, but it turned out to be something related to the upgrade. Using the archive of Spotify CEF builds I've narrowed it down to being introduced at CEF's switch to Chromium major 64. I'm able to reproduce this issue almost 100% with any build greater or equal to CEF 3.3282.1728.g2171fc7 / Chromium 64.0.3282.119 and not at all with any build preceding it (starting with CEF 3.3239.1723.g071d1c1 / Chromium 63.0.3239.132).
I'll probably end up employing the same kind of fix/hack as described by ScottKevill, but I share the sentiment that having to rely on CefShutdown for cleanup of the child processes is somewhat unrealistic, if this is by design that is.
Anyway, I mostly just want to drive home the point that this issue has (in my experience) a point in time where it's become significantly more prevalent.
You can view a call stack of the zombie processes on this ticket here. Let me know if there's any more information you need.
magreenblatt wrote:Can you file a CEF issue for this? Thanks.
#include <thread>
#include <tlhelp32.h>
HANDLE GetParentProcess()
{
HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 ProcessEntry = {};
ProcessEntry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(Snapshot, &ProcessEntry))
{
DWORD CurrentProcessId = GetCurrentProcessId();
do
{
if (ProcessEntry.th32ProcessID == CurrentProcessId)
break;
} while (Process32Next(Snapshot, &ProcessEntry));
}
CloseHandle(Snapshot);
return OpenProcess(SYNCHRONIZE, FALSE, ProcessEntry.th32ParentProcessID);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ShowCmd)
{
HANDLE ParentProcess = GetParentProcess();
std::thread([ParentProcess]()
{
WaitForSingleObject(ParentProcess, INFINITE);
ExitProcess(0);
}).detach();
CefMainArgs MainArgs(hInstance);
return CefExecuteProcess(MainArgs, /* ... */);
}
callum wrote:@Mikael - I'm working through it now but can you highlight which of those calls is 32bit only? Our application is 64 bit and I want to try a version of this in our code to see if it helps.
Users browsing this forum: Google [Bot] and 47 guests