chromiumembedded / cef

Chromium Embedded Framework (CEF). A simple framework for embedding Chromium-based browsers in other applications.
https://bitbucket.org/chromiumembedded/cef/
Other
3.38k stars 467 forks source link

Second `cef_initialize()` call crashes libcef #3774

Closed sergio-nsk closed 2 months ago

sergio-nsk commented 3 months ago

Want to do smth like this

if (!cef_initialize(&main_args, &settings, <...>) &&
    cef_get_exit_code() == CEF_RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED) {
  // change settings.cache_path
  cef_initialize(&main_args, &settings, <...>);
}

It crashes in the second call after the change https://bitbucket.org/chromiumembedded/cef/commits/a25f89f9e4a5b702de4f0e4726cfee2f4f94426b in libcef/browser/context.cc:

  g_context = new CefContext();

  // Initialize the global context.
-   return g_context->Initialize(args, settings, application,
-                                windows_sandbox_info);
+   if (!g_context->Initialize(args, settings, application,
+                              windows_sandbox_info)) {
+     // Initialization failed. Delete the global context object.
+     delete g_context;
+     g_context = nullptr;
+     return false;

  return true;
}

void CefShutdown() {

because Chromium does not allow to reassign the ContentMainDelegate: https://chromium.googlesource.com/chromium/src.git/+/refs/tags/127.0.6533.120/content/app/content_main_runner_impl.cc#1080

void ContentMainRunnerImpl::ReInitializeParams(ContentMainParams new_params) {
  DCHECK(!content_main_params_);
  // Initialize() already set |delegate_|, expect the same one.
  DCHECK_EQ(delegate_, new_params.delegate);
  new_params.delegate = nullptr;
  content_main_params_.emplace(std::move(new_params));
}

The delegate was reset in ContentMainRunnerImpl::Shutdown() while CefContext() destroying.

Expected behavior

cef_initialize() can be called more than one time.

Versions (please complete the following information):

Additional context

I think reverting the changes in libcef/browser/context.cc and making the change below will resolve the issue.

- CefContext* g_context = nullptr;
+ CefContext* GetContext() {
+   static base::NoDestructor<CefContext> context;
+   return &context;
+ }
cmf41013 commented 3 months ago

It's not a bug.

Did you ever read CefInitialize or cef_initialize comments?

"If this function returns false then the application should exit immediately without calling any other CEF functions except, optionally, CefGetErrorCode."

sergio-nsk commented 3 months ago

@cmf41013 "Any other CEF functions" - cef_initialize is not other functions. Hence, it's legitimate to call it again and It did not crash prior CEF 120. Moreover, Chromium allows the reinitialization.

cmf41013 commented 3 months ago

@cmf41013 "Any other CEF functions" - cef_initialize is not other functions. Hence, it's legitimate to call it again and It did not crash prior CEF 120. Moreover, Chromium allows the reinitialization.

“the application should exit immediately”,and Chromium allows the reinitialization has no effect on that cef can't initialize multiple times. Did cef documents say or imply that it can initialize mutiple times in versions prior CEF 120? no crashing can not testify it is allowable.

If you don't call any other cef functions after calling cef_initialize , then why do you call the cef_initialize function again? So what's the point of no calling other cef function in a cef application?

sergio-nsk commented 2 months ago

Did cef documents say or imply that it can initialize mutiple times in versions prior CEF 120?

It allowed that.

/// This function should be called on the main application thread to initialize
/// the CEF browser process. The |application| parameter may be NULL. A return
/// value of true (1) indicates that it succeeded and false (0) indicates that
/// it failed. The |windows_sandbox_info| parameter is only used on Windows and
/// may be NULL (see cef_sandbox_win.h for details).

If you don't call any other cef functions after calling cef_initialize , then why do you call the cef_initialize function again? So what's the point of no calling other cef function in a cef application?

I don't understand the meaning of this stream of words.

magreenblatt commented 2 months ago

Calling CefInitialize multiple times is not supported usage.