Fix deadlock on device loss

Some backends generate a device loss (propagated to all contexts) while
querying the device status.  The latter is held under a lock, and the
former would attempt to hold the lock when marking the calling context
with device loss.

Bug: chromium:1465262
Change-Id: I55fd96f3573732953daf2a305b0120dbcae6ea30
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4690063
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Shahbaz Youssefi
2023-07-17 11:32:23 -04:00
committed by Angle LUCI CQ
parent e8e17211e2
commit bd8001e581
2 changed files with 15 additions and 1 deletions

View File

@@ -9952,6 +9952,17 @@ void ErrorSet::validationErrorF(angle::EntryPoint entryPoint,
}
}
std::unique_lock<std::mutex> ErrorSet::getLockIfNotAlready()
{
// Avoid mutex recursion and return the lock only if it is not already locked. This can happen
// if device loss is generated while it is being queried.
if (mMutex.try_lock())
{
return std::unique_lock<std::mutex>(mMutex, std::adopt_lock);
}
return std::unique_lock<std::mutex>();
}
void ErrorSet::pushError(GLenum errorCode)
{
ASSERT(errorCode != GL_NO_ERROR);
@@ -9979,7 +9990,9 @@ GLenum ErrorSet::popError()
// NOTE: this function should not assume that this context is current!
void ErrorSet::markContextLost(GraphicsResetStatus status)
{
std::lock_guard<std::mutex> lock(mMutex);
// This function may be called indirectly through ErrorSet::getGraphicsResetStatus() from the
// backend, in which case mMutex is already held.
std::unique_lock<std::mutex> lock = getLockIfNotAlready();
ASSERT(status != GraphicsResetStatus::NoError);
if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)

View File

@@ -124,6 +124,7 @@ class ErrorSet : angle::NonCopyable
private:
void setContextLost();
void pushError(GLenum errorCode);
std::unique_lock<std::mutex> getLockIfNotAlready();
// Non-atomic members of this class are protected by a mutex. This is to allow errors to be
// safely set by entry points that don't hold a lock. Note that other contexts may end up