C++ CEF base::ThreadRestrictions::AssertionAllowed()断言在应用程序退出时失败

C++ CEF base::ThreadRestrictions::AssertionAllowed()断言在应用程序退出时失败,c++,macos,chromium-embedded,C++,Macos,Chromium Embedded,我有一个简单的OSX CEF应用程序,它基于提供的CEF示例应用程序。一个值得注意的变化是我在单进程模式下运行(settings.single\u process=true)。由于断言失败,我在退出时遇到崩溃。奇怪的是,这种崩溃也发生在发布版本中,而不仅仅是调试版本 任何人(CEF大师)能帮助我理解这里的问题吗?stacktrace说我正在从一个不允许IO的线程调用一个“仅IO”函数。我正在做的唯一IO就是从应用程序包中加载静态html文件。这似乎不需要特别处理。但是,好吧,让我们假设它确实需要

我有一个简单的OSX CEF应用程序,它基于提供的CEF示例应用程序。一个值得注意的变化是我在单进程模式下运行(
settings.single\u process=true
)。由于断言失败,我在退出时遇到崩溃。奇怪的是,这种崩溃也发生在发布版本中,而不仅仅是调试版本

任何人(CEF大师)能帮助我理解这里的问题吗?stacktrace说我正在从一个不允许IO的线程调用一个“仅IO”函数。我正在做的唯一IO就是从应用程序包中加载静态html文件。这似乎不需要特别处理。但是,好吧,让我们假设它确实需要我按照断言错误中的建议“在该线程的启动中调整对base::ThreadRestrictions::SetIOAllowed()的调用”——我不知道如何或在何处这样做

以下是stacktrace:

[1120/110258:FATAL:thread_restrictions.cc(38)] Function marked as IO-only was called from a thread that disallows IO!  If this thread really should be allowed to make IO calls, adjust the call to base::ThreadRestrictions::SetIOAllowed() in this thread's startup.
0   Chromium Embedded Framework         0x0068b8cf base::debug::StackTrace::StackTrace() + 63
1   Chromium Embedded Framework         0x0068b92b base::debug::StackTrace::StackTrace() + 43
2   Chromium Embedded Framework         0x00719d52 logging::LogMessage::~LogMessage() + 82
3   Chromium Embedded Framework         0x00718a8b logging::LogMessage::~LogMessage() + 43
4   Chromium Embedded Framework         0x00832984 base::ThreadRestrictions::AssertIOAllowed() + 276
5   Chromium Embedded Framework         0x00810100 base::PlatformThread::Join(base::PlatformThreadHandle) + 48
6   Chromium Embedded Framework         0x008263a3 base::Thread::Stop() + 131
7   Chromium Embedded Framework         0x08413d8f content::InProcessRendererThread::~InProcessRendererThread() + 63
8   Chromium Embedded Framework         0x08413e0b content::InProcessRendererThread::~InProcessRendererThread() + 43
9   Chromium Embedded Framework         0x08413e5e content::InProcessRendererThread::~InProcessRendererThread() + 46
10  Chromium Embedded Framework         0x07bab824 base::DefaultDeleter<base::Thread>::operator()(base::Thread*) const + 68
11  Chromium Embedded Framework         0x07bab7aa base::internal::scoped_ptr_impl<base::Thread, base::DefaultDeleter<base::Thread> >::reset(base::Thread*) + 122
12  Chromium Embedded Framework         0x07b93bc9 scoped_ptr<base::Thread, base::DefaultDeleter<base::Thread> >::reset(base::Thread*) + 57
13  Chromium Embedded Framework         0x07b85dc8 content::RenderProcessHostImpl::~RenderProcessHostImpl() + 392
14  Chromium Embedded Framework         0x07b8632b content::RenderProcessHostImpl::~RenderProcessHostImpl() + 43
15  Chromium Embedded Framework         0x07b864be content::RenderProcessHostImpl::~RenderProcessHostImpl() + 46
16  Chromium Embedded Framework         0x00534d88 CefContentRendererClient::RunSingleProcessCleanupOnUIThread() + 872
17  Chromium Embedded Framework         0x00534888 CefContentRendererClient::RunSingleProcessCleanup() + 344
18  Chromium Embedded Framework         0x003d6ab5 CefContext::FinalizeShutdown() + 69
19  Chromium Embedded Framework         0x003d5b26 CefContext::Shutdown() + 694
20  Chromium Embedded Framework         0x003d5750 CefShutdown() + 512
21  Chromium Embedded Framework         0x0027dbe7 cef_shutdown + 39
22  CEFSimpleSample                     0x000c1a37 CefShutdown() + 39
23  CEFSimpleSample                     0x000baefc main + 388
24  libdyld.dylib                       0x96e33701 start + 1
25  ???                                 0x00000003 0x0 + 3
[1120/110258:FATAL:thread_restrictions.cc(38)]标记为仅IO的函数是从不允许IO的线程调用的!如果确实应该允许此线程进行IO调用,请在该线程的启动中调整对base::ThreadRestrictions::SetIOAllowed()的调用。
0 Chromium嵌入式框架0x0068b8cf base::debug::StackTrace::StackTrace()+63
1 Chromium嵌入式框架0x0068b92b base::debug::StackTrace::StackTrace()+43
2 Chromium嵌入式框架0x00719d52日志::LogMessage::~LogMessage()+82
3 Chromium嵌入式框架0x00718a8b日志::LogMessage::~LogMessage()+43
4 Chromium嵌入式框架0x00832984 base::ThreadRestrictions::AssertionAllowed()+276
5铬嵌入式框架0x00810100 base::PlatformThread::Join(base::PlatformThreadHandle)+48
6铬嵌入式框架0x008263a3 base::Thread::Stop()+131
7 Chromium嵌入式框架0x08413d8f内容::InProcessRenderThread::~InProcessRenderThread()+63
8 Chromium嵌入式框架0x08413e0b内容::InProcessRenderThread::~InProcessRenderThread()+43
9 Chromium嵌入式框架0x08413e5e内容::InProcessRenderThread::~InProcessRenderThread()+46
10 Chromium嵌入式框架0x07bab824 base::DefaultDeleter::operator()(base::Thread*)常量+68
11 Chromium嵌入式框架0x07bab7aa base::internal::scoped_ptr_impl::reset(base::Thread*)+122
12铬嵌入式框架0x07b93bc9作用域_ptr::reset(base::Thread*)+57
13 Chromium嵌入式框架0x07b85dc8内容::RenderProcessHostImpl::~RenderProcessHostImpl()+392
14 Chromium嵌入式框架0x07b8632b内容::RenderProcessHostImpl::~RenderProcessHostImpl()+43
15 Chromium嵌入式框架0x07b864be内容::RenderProcessHostImpl::~RenderProcessHostImpl()+46
16 Chromium嵌入式框架0x00534d88 CEFContentRenderClient::RunSingleProcessCleanupOnUIThread()+872
17 Chromium嵌入式框架0x00534888 CEFContentRenderClient::RunSingleProcessCleanup()+344
18 Chromium嵌入式框架0x003d6ab5 CefContext::FinalizeShutdown()+69
19铬嵌入式框架0x003d5b26 CefContext::Shutdown()+694
20铬嵌入式框架0x003d5750()+512
21铬嵌入式框架0x0027dbe7 cef_关闭+39
22 CEFSimpleSample 0x000c1a37 CEFSupdown()+39
23 CEFSimpleSample 0x000baefc干管+388
24 libdyld.dylib 0x96e33701开始+1
25  ???                                 0x00000003 0x0+3
这是我应用程序的一部分。CEFShutdown()方法中的断言失败,它是一个框架方法:

// Entry point function for the browser process.
int main(int argc, char* argv[]) {
    // Provide CEF with command-line arguments.
    CefMainArgs main_args(argc, argv);

    // ClientHandler implements application-level callbacks. It will create the first
    // browser instance in OnContextInitialized() after CEF has initialized.
    CefRefPtr<ClientHandler> app(new ClientHandler);

    // Initialize the AutoRelease pool.
    NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init];

    // Initialize the SimpleApplication instance.
    [SimpleApplication sharedApplication];

    // Specify CEF global settings here.
    CefSettings settings;
    settings.single_process = true;

    // Initialize CEF for the browser process.
    CefInitialize(main_args, settings, app.get(), NULL);

    // Create the application delegate.
    NSObject* delegate = [[SimpleAppDelegate alloc] init];
    [delegate performSelectorOnMainThread:@selector(createApplication:)
                               withObject:nil
                            waitUntilDone:NO];

    // Run the CEF message loop. This will block until CefQuitMessageLoop() is
    // called.
    CefRunMessageLoop();

    // Shut down CEF.
    CefShutdown();

    // Release the delegate.
    [delegate release];

    // Release the AutoRelease pool.
    [autopool release];

    return 0;
}
//浏览器进程的入口点函数。
int main(int argc,char*argv[]){
//为CEF提供命令行参数。
CefMainArgs main_args(argc,argv);
//ClientHandler实现应用程序级回调
//CEF初始化后OnContextInitialized()中的浏览器实例。
CefRefPtr应用程序(新ClientHandler);
//初始化自动释放池。
NSAutoreleasePool*autopool=[[NSAutoreleasePool alloc]init];
//初始化SimpleApplication实例。
[SimpleApplication sharedApplication];
//在此处指定CEF全局设置。
环境设置;
settings.single_process=true;
//初始化浏览器进程的CEF。
CEFPinitialize(主参数、设置、app.get()、NULL);
//创建应用程序委托。
NSObject*delegate=[[SimpleAppDelegate alloc]init];
[委托performSelectorOnMainThread:@selector(createApplication:)
withObject:零
waitUntilDone:没有];
//运行CEF消息循环。这将一直阻止,直到执行CefQuitMessageLoop()
//打电话来。
CefRunMessageLoop();
//关闭CEF。
CefShutdown();
//释放代理。
[授权释放];
//释放自动释放池。
[自动工具释放];
返回0;
}

这是CEF的一个已知错误:

Chromium通常将UI线程与IO线程区分开来,并且消息是一个断言,表明这些线程是混合的。它与您自己的IO无关

您需要查看堆栈以了解发生了什么。具有命名空间的函数通常属于Chromium,而全局命名空间中的函数是CEF本身的一部分。和CEF相关的崩溃通常是由于胶水嵌入铬

有罪函数可能是CefContentRenderClient的方法。该名称意味着它要在UI线程上运行

void CefContentRendererClient::RunSingleProcessCleanupOnUIThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  // Clean up the single existing RenderProcessHost.
  content::RenderProcessHost* host = NULL;
  content::RenderProcessHost::iterator iterator(
      content::RenderProcessHost::AllHostsIterator());
  if (!iterator.IsAtEnd()) {
    host = iterator.GetCurrentValue();
    host->Cleanup();
    iterator.Advance();
    DCHECK(iterator.IsAtEnd());
  }
  DCHECK(host);

  // Clear the run_renderer_in_process() flag to avoid a DCHECK in the
  // RenderProcessHost destructor.
  content::RenderProcessHost::SetRunRendererInProcess(false);

  // Deletion of the RenderProcessHost object will stop the render thread and
  // result in a call to WillDestroyCurrentMessageLoop.
  // Cleanup() will cause deletion to be posted as a task on the UI thread but
  // this task will only execute when running in multi-threaded message loop
  // mode (because otherwise the UI message loop has already stopped). Therefore
  // we need to explicitly delete the object when not running in this mode.
  if (!CefContext::Get()->settings().multi_threaded_message_loop)
    delete host;
}
崩溃发生在函数的最底层。实际上,
multi_-threaded\u message\u loop
为false(
multi_-threaded\u message\u loop
仅适用于Windows),我们可以跟踪堆栈跟踪中的崩溃,以找到RenderProcessHostImpl析构函数

// Teardown may start in PostMainMessageLoopRun, and during teardown we
// need to be able to perform IO.
base::ThreadRestrictions::SetIOAllowed(true);
BrowserThread::PostTask(
    BrowserThread::IO, FROM_HERE,
    base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
             true));