CEF RenderProcessHandler's callback methods not being hit

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.

Re: CEF RenderProcessHandler's callback methods not being hi

Postby amaitland » Tue Jun 15, 2021 4:45 am

You don't need to attach type=renderer, chromium will launch the sub processes with the appropriate command line args.

Sandbox is optional.

I cannot say if your main entry point is correct as the example you provided is incomplete.

You can set the log path via CefSettings.
Maintainer of the CefSharp project.
amaitland
Master
 
Posts: 969
Joined: Wed Jan 14, 2015 2:35 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby michaelb » Tue Jun 15, 2021 6:00 am

Okay, so I reran the program with the log file enabled and redirected to a known path, and the
Code: Select all
--renderer-startup-dialog --no-sandbox
command line arguments, where I got the behavior of the multiple popups for the render process pid. About 2-4 in the beginning of each run. I attached all of them to the VS debugger. This time they didn't keep on popping back up again. However, my app's RenderProcessHandler's event callback methods did not get hit (after browser created, I attached the processes to debugger, then there was a sleep for a few minutes, then the browser was closed, and my breakpoint in OnBrowserDestroyed in my app did not get hit). There was nothing special or errors in the logs, however we do see that the render process(es) are running.

At this point I am very stuck. What else could it be?

This is the entire main entry point:
Code: Select all
    CEFManager(int port)
    {
        char pathStr[MAX_PATH];
#ifdef _WIN32
        ::GetModuleFileName(NULL, pathStr, MAX_PATH);
#else
        auto pathStrLen = readlink("/proc/self/exe", pathStr, MAX_PATH);
        pathStr[pathStrLen] = '\0'; // readlink returns non-null-terminating strings, so terminate.
#endif

#ifndef _WIN64
        char** args = new char*[1];
        args[0] = pathStr;
        CefMainArgs mainArgs(1, args);
#else
        CefMainArgs mainArgs(GetModuleHandle(NULL));
#endif
        CefRefPtr<RendererApp> app = new RendererApp();

        int exit_code = CefExecuteProcess(mainArgs, app.get(), nullptr);

        CefSettings settings;

        std::string path = pathStr;
        auto loc = path.find_last_of('/');
        if (loc == std::string::npos)
        {
            loc = path.find_last_of('\\');
        }
        auto const WORKER_PATH = path.substr(0, loc + 1) +
#ifndef _WIN64
            "CEFWorker";
#else
            "CEFWorker.exe";
#endif
        if (!boost::filesystem::exists(WORKER_PATH))
        {
            Logger::getInstance().logMessage(Severity::FATAL_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__, "CEF Worker executable not found at %s", WORKER_PATH.c_str());
        }
        CefString(&settings.browser_subprocess_path).FromASCII(WORKER_PATH.c_str());
        settings.no_sandbox = true;
        settings.log_severity = LOGSEVERITY_VERBOSE;
        CefString(&settings.log_file) = path.substr(0, loc + 1) + "cef_debug.log";
        settings.windowless_rendering_enabled = true;
        settings.multi_threaded_message_loop = true;
        settings.remote_debugging_port = port;
        Logger::getInstance().logMessage(Severity::INFO_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__, "HeadlessBrowser Runnig on Port %d", port);

        // If not in Windows, take locales and resources from PATH
#ifndef _WIN64
        const std::string RESOURCES_DIR_PATH = "/opt/cef/resources";
        CefString(&settings.resources_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());
        CefString(&settings.locales_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());

        Logger::getInstance().logMessage(Severity::INFO_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__,
            "CEF Headless browser looking for resources in %s", RESOURCES_DIR_PATH.c_str());
#else
        bool success = false;
        const std::string RESOURCES_DIR_PATH = Utils::getVenueInstalledDirectory() + "\\Bin";
        CefString(&settings.resources_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());
        CefString(&settings.locales_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());

        Logger::getInstance().logMessage(Severity::INFO_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__,
            "CEF Headless browser looking for resources in %s", RESOURCES_DIR_PATH.c_str());
#endif

        // Initialize CEF.
        _initializedCorrectly = CefInitialize(mainArgs, settings, app, nullptr);
    }

    bool _initializedCorrectly = false;
};
michaelb
Techie
 
Posts: 20
Joined: Thu May 20, 2021 7:38 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby amaitland » Tue Jun 15, 2021 2:35 pm

You don't appear to be handling the CefExecuteProcess call correctly, you need to exit the process if it returns greater than -1.

Is your main application CEFWorker.exe? Or are you using a separate executable for the sub process?
Maintainer of the CefSharp project.
amaitland
Master
 
Posts: 969
Joined: Wed Jan 14, 2015 2:35 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby michaelb » Wed Jun 16, 2021 1:46 am

It's returning -1, but it's supposed to be the render process not the browser process. It might be something we need to fix but I am not sure that is the issue causing the render process not to hit our overriden callback methods.
I think there are separate CEFWorker.exes, when we run our program I see 4-5 CEFWorker.exes in the task manager.

The render processes start up much later in our code on browser creation, but these are not the render processes we want that redirect to our overridden callback code... this CefExecuteProcess call is what we want to be the render process, and then upon browser startup, using this render process with our callback functions.

Or is the browser creation supposed to start render processes that automatically redirect to our callback functions in our app that extends CefApp & CefRenderHandler, but then what would be the point of doing CefExecuteProcess on the render process, which returns -1 anyways?
michaelb
Techie
 
Posts: 20
Joined: Thu May 20, 2021 7:38 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby amaitland » Wed Jun 16, 2021 2:15 am

Or is the browser creation supposed to start render processes that automatically redirect to our callback functions in our app that extends CefApp & CefRenderHandler, but then what would be the point of doing CefExecuteProcess on the render process, which returns -1 anyways?


You seem to have gotten rather confused about how the process model works. You don't call CefExecuteProcess to spawn a render process. The fact that it's returning -1 means you are in the browser process (your main application). Chromium will spawn multiple instances of your application or a separate executable to host the sub processes.

You need to add your render handler code to CEFWorker.exe.

Is there someone in your dev team who did the initial implementation? Be really useful if there was someone you could ask for guidance in person.
Maintainer of the CefSharp project.
amaitland
Master
 
Posts: 969
Joined: Wed Jan 14, 2015 2:35 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby michaelb » Wed Jun 16, 2021 2:45 am

So, CefExecuteProcess doesn't spawn a new process?
Yes, I am in the main application entry point... so it's good that it's returning -1?

Our render handler code is inside "RendererApp", which we are passing into CefExecuteProcess and CefInitialize ... isn't this how to attach it to CEFWorker.exe (the exe name in the main entry point)? Or is something missing?

Yes, there were other people who did the initial implementation, I am new and inherited that code, not sure if the other people are still around or available but I could look into that. In any case, the code I shared is our entire application entry point, so it all should be in there. There was no CefExecuteProcess - that is me attempting to add that in order to hit our RenderProcessHandler javascript binding code. I will reshare the code here for convenience.

Code: Select all
    CEFManager(int port)
    {
        char pathStr[MAX_PATH];
#ifdef _WIN32
        ::GetModuleFileName(NULL, pathStr, MAX_PATH);
#else
        auto pathStrLen = readlink("/proc/self/exe", pathStr, MAX_PATH);
        pathStr[pathStrLen] = '\0'; // readlink returns non-null-terminating strings, so terminate.
#endif

#ifndef _WIN64
        char** args = new char*[1];
        args[0] = pathStr;
        CefMainArgs mainArgs(1, args);
#else
        CefMainArgs mainArgs(GetModuleHandle(NULL));
#endif
        CefRefPtr<RendererApp> app = new RendererApp();

        int exit_code = CefExecuteProcess(mainArgs, app.get(), nullptr);

        CefSettings settings;

        std::string path = pathStr;
        auto loc = path.find_last_of('/');
        if (loc == std::string::npos)
        {
            loc = path.find_last_of('\\');
        }
        auto const WORKER_PATH = path.substr(0, loc + 1) +
#ifndef _WIN64
            "CEFWorker";
#else
            "CEFWorker.exe";
#endif
        if (!boost::filesystem::exists(WORKER_PATH))
        {
            Logger::getInstance().logMessage(Severity::FATAL_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__, "CEF Worker executable not found at %s", WORKER_PATH.c_str());
        }
        CefString(&settings.browser_subprocess_path).FromASCII(WORKER_PATH.c_str());
        settings.no_sandbox = true;
        settings.log_severity = LOGSEVERITY_VERBOSE;
        CefString(&settings.log_file) = path.substr(0, loc + 1) + "cef_debug.log";
        settings.windowless_rendering_enabled = true;
        settings.multi_threaded_message_loop = true;
        settings.remote_debugging_port = port;
        Logger::getInstance().logMessage(Severity::INFO_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__, "HeadlessBrowser Runnig on Port %d", port);

        // If not in Windows, take locales and resources from PATH
#ifndef _WIN64
        const std::string RESOURCES_DIR_PATH = "/opt/cef/resources";
        CefString(&settings.resources_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());
        CefString(&settings.locales_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());

        Logger::getInstance().logMessage(Severity::INFO_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__,
            "CEF Headless browser looking for resources in %s", RESOURCES_DIR_PATH.c_str());
#else
        bool success = false;
        const std::string RESOURCES_DIR_PATH = Utils::getVenueInstalledDirectory() + "\\Bin";
        CefString(&settings.resources_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());
        CefString(&settings.locales_dir_path).FromASCII(RESOURCES_DIR_PATH.c_str());

        Logger::getInstance().logMessage(Severity::INFO_LEVEL, "CEF", __FUNCTION__, __FILE__, __LINE__,
            "CEF Headless browser looking for resources in %s", RESOURCES_DIR_PATH.c_str());
#endif

        // Initialize CEF.
        _initializedCorrectly = CefInitialize(mainArgs, settings, app, nullptr);
    }

    bool _initializedCorrectly = false;
};
michaelb
Techie
 
Posts: 20
Joined: Thu May 20, 2021 7:38 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby amaitland » Wed Jun 16, 2021 4:27 am

So, CefExecuteProcess doesn't spawn a new process?


That's correct.

Yes, I am in the main application entry point... so it's good that it's returning -1?


That's expected. Basically means it recognised your are in the main application and does nothing. It would block until completion otherwise.

There was no CefExecuteProcess - that is me attempting to add that in order to hit our RenderProcessHandler javascript binding code. I will reshare the code here for convenience.


The sub process won't run without `CefExecuteProcess ` and based on the browser_subprocess_path it's very likely that you are using a separate exe for the sub process.

My guess is that CEFWorker.exe is an entirely different application. You need to find the source for `CEFWorker.exe`
Maintainer of the CefSharp project.
amaitland
Master
 
Posts: 969
Joined: Wed Jan 14, 2015 2:35 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby michaelb » Wed Jun 16, 2021 4:53 am

So we don't have any source code for CefWorker.exe
Just the main application entry point code, which references this as the browser sub-process path.
Could this in and of itself be the issue, that we need to implement the sub-process entry point? And since we didn't, the "CefWorker.exes" that run are just some default/empty ones? Something has to be running them though as they appear in task manager and we are checking for their existence in the main application entry point, yet we don't have any source code for it...
michaelb
Techie
 
Posts: 20
Joined: Thu May 20, 2021 7:38 am

Re: CEF RenderProcessHandler's callback methods not being hi

Postby michaelb » Wed Jun 16, 2021 5:22 am

Update: I found the source code for our CefWorker.exe
I will look into it. thanks
michaelb
Techie
 
Posts: 20
Joined: Thu May 20, 2021 7:38 am

Previous

Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 16 guests