Page 1 of 1

CefV8Handler child class not retaining object state

PostPosted: Wed Apr 21, 2021 1:30 pm
by natonicfp
Probably missing something really obvious here, but I am unsure what it is. I subclassed CefV8Handler to create MyCefV8Handler which receives and stores information from the back end in a resources data member which is converted to a Cef array and returned when requested by a JS "get_resources" function call. That JS function was created in the OnContextCreated handler of my renderer process app object.

I am sending the data using SendProcessMessage and have confirmed that the data is received and stored in the MyCefV8Handler::resources data member (inside the CefApp::OnProcessMessageReceived handler). I am logging the received data with LOG(INFO)). I'm also logging the address of the resources data member at this time.

When the MyCefV8Handler::Execute call occurs, I log the address of the resources data member and its content.

I have confirmed that the resources data member is updated before the Execute call occurs (both in terms of the sequence of log messages and because I put a thread wait in the browser process right after sending the process message and confirmed the message was received and processed before the browser process thread continued). I've also confirmed that the resources data member address is the same in the message received handler and in the Execute call, so I know I'm accessing the same memory.

Even with these validations, I find that inside the Execute call the data member is empty. Sometime between the update from the message handler and the retrieval of the data from the same object (based on the address logged at each point) the data is cleared out. There is only one mutator for the data member and it logs the object address every time it is called. It is only called once.

I realize that it is possible this issue has nothing to do with CEF, but I wanted to see if I have violated some assumption about object state for a CefV8Handler before I look for something even more fundamental.

Any insights on what might be going on with this?

Re: CefV8Handler child class not retaining object state

PostPosted: Wed Apr 21, 2021 4:48 pm
by natonicfp
I doubt this is related, and probably just has to do with how the V8 engine works, but out of curiosity I spit out the PID (from ::getpid()) for each process as it started and then tried to spit it out when the V8 context is created as well as when Execute is called and when OnProcessMessageReceived is called. The PIDs in the V8 context (CefRenderProcessHandler::OnContextCreated, CefV8Handler::Execute, and CefRenderProcessHandler::OnProcessMessageReceived) all come out as 1 instead of one of the launched process ids.

Re: CefV8Handler child class not retaining object state

PostPosted: Thu Apr 22, 2021 5:20 pm
by natonicfp
I have done some further investigation into this and it would appear that my tests for verifying I was in the same renderer process when I received the process message as I was when the V8 Execute call was made were invalid. I had assumed that the data member's address being unchanged between those two points was confirmation that it was the same data member. I tested this theory further today by logging when constructors and destructors were called on the various objects of interest as well as a new static object created for the purpose of the test. It turns out that the destructors of all the objects are called almost immediately after the OnProcessMessageReceived call completes, and that their constructors are called again when the request to execute the V8 JS function is received in MyCefV8Handler.

This would seem to indicate that the renderer process is being started and stopped multiple times and mapped into exactly the same part of memory on the subsequent execution.

I don't know why that would be, but regardless, it would seem to indicate that the renderer process should be treated as stateless and any needed state maintained by other means such as shared memory, the file system, or other persistent mechanisms.

I'm proceeding with this assumption, but would love to be corrected on it if I'm mistaken.

Re: CefV8Handler child class not retaining object state

PostPosted: Thu Apr 22, 2021 5:54 pm
by magreenblatt
There may be multiple renderer processes. You can store per-process state as members of your CefRenderProcessHandler implementation. See for example ... t-bindings

Re: CefV8Handler child class not retaining object state

PostPosted: Thu Apr 22, 2021 9:12 pm
by natonicfp
Thanks for the reply. I didn't see examples of application state kept in the CefRenderProcessHandler in the link to the asynchronous javascript binding section you sent, but it did appear that both the message router and the custom implementation examples in that spot rely upon the browser process to perform any significant work (or retrieval stateful information) and that they both use the IPC mechanism and retain the callback for a javascript function call in the current V8 context so that it can be retrieved and completed from that context when the browser process sends a result via IPC. Is this what you were driving at or did I miss the point?

Regarding there being multiple renderer processes, I'm noticing that, but it seems that the factors that determine whether and when additional renderer processes will be initiated and when others will exit is opaque, and probably not something my application code should be relying upon.

If I understand your second command about per-process state as members of the CefRenderProcessHandler implementation, I'm not sure that will help in my application, as the state I'm tracking needs to be available for an arbitrary period of time (apparently without reference to the lifespan of a renderer process since I don't have control of that anyway).

Re: CefV8Handler child class not retaining object state

PostPosted: Sun May 02, 2021 3:25 pm
by natonicfp
After digging into the links @magreenblatt sent, I ended up just implementing the CEF Message Router in my application and using the cefQuery mechanism to pull state from the browser process native code. This is working fine and is easier to manage since it leaves the render process code pretty vanilla and all the interesting native code stuff happening in the browser process where I have more control over the life cycle of the process. Thanks for the pointers.