Make error scope shutdown iterative instead of recursive.

This avoids a stack overflow when many error scopes are pushed on device
shutdown. It also changes the error scopes to return a Unknown error
type on shutdown instead of NoError.

A regression test is added.

Bug: chromium:1078438
Bug: chromium:1081063
Change-Id: Ibfab8dd19480414c1854ec2bd4928939663ba698
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/21440
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez
2020-05-11 20:26:12 +00:00
committed by Commit Bot service account
parent c2542cde3e
commit a6cf7b5b1d
5 changed files with 53 additions and 13 deletions

View File

@@ -18,18 +18,18 @@
namespace dawn_native {
ErrorScope::ErrorScope() = default;
ErrorScope::ErrorScope() : mIsRoot(true) {
}
ErrorScope::ErrorScope(wgpu::ErrorFilter errorFilter, ErrorScope* parent)
: RefCounted(), mErrorFilter(errorFilter), mParent(parent) {
: RefCounted(), mErrorFilter(errorFilter), mParent(parent), mIsRoot(false) {
ASSERT(mParent.Get() != nullptr);
}
ErrorScope::~ErrorScope() {
if (mCallback == nullptr || IsRoot()) {
return;
if (!IsRoot()) {
RunNonRootCallback();
}
mCallback(static_cast<WGPUErrorType>(mErrorType), mErrorMessage.c_str(), mUserdata);
}
void ErrorScope::SetCallback(wgpu::ErrorCallback callback, void* userdata) {
@@ -42,13 +42,27 @@ namespace dawn_native {
}
bool ErrorScope::IsRoot() const {
return mParent.Get() == nullptr;
return mIsRoot;
}
void ErrorScope::RunNonRootCallback() {
ASSERT(!IsRoot());
if (mCallback != nullptr) {
// For non-root error scopes, the callback can run at most once.
mCallback(static_cast<WGPUErrorType>(mErrorType), mErrorMessage.c_str(), mUserdata);
mCallback = nullptr;
}
}
void ErrorScope::HandleError(wgpu::ErrorType type, const char* message) {
HandleErrorImpl(this, type, message);
}
void ErrorScope::UnlinkForShutdown() {
UnlinkForShutdownImpl(this);
}
// static
void ErrorScope::HandleErrorImpl(ErrorScope* scope, wgpu::ErrorType type, const char* message) {
ErrorScope* currentScope = scope;
@@ -105,10 +119,24 @@ namespace dawn_native {
}
}
void ErrorScope::Destroy() {
if (!IsRoot()) {
mErrorType = wgpu::ErrorType::Unknown;
mErrorMessage = "Error scope destroyed";
// static
void ErrorScope::UnlinkForShutdownImpl(ErrorScope* scope) {
Ref<ErrorScope> currentScope = scope;
Ref<ErrorScope> parentScope = nullptr;
for (; !currentScope->IsRoot(); currentScope = parentScope.Get()) {
ASSERT(!currentScope->IsRoot());
ASSERT(currentScope.Get() != nullptr);
parentScope = std::move(currentScope->mParent);
ASSERT(parentScope.Get() != nullptr);
// On shutdown, error scopes that have yet to have a status get Unknown.
if (currentScope->mErrorType == wgpu::ErrorType::NoError) {
currentScope->mErrorType = wgpu::ErrorType::Unknown;
currentScope->mErrorMessage = "Error scope destroyed";
}
// Run the callback if it hasn't run already.
currentScope->RunNonRootCallback();
}
}