C++ CEF base::ThreadRestrictions::AssertionAllowed()断言在应用程序退出时失败
我有一个简单的OSX CEF应用程序,它基于提供的CEF示例应用程序。一个值得注意的变化是我在单进程模式下运行(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文件。这似乎不需要特别处理。但是,好吧,让我们假设它确实需要
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));