[wire] Fix potential lock inversion in buffer mapping. - The potential lock inversion was introduced in https://dawn-review.git.corp.google.com/c/dawn/+/317816. This change ensures that the inversion can no longer occur. Bug: 529413629 Change-Id: I848b68630e951d642eaf5175d39b7a02cd29d902 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/321995 Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/wire/client/Buffer.cpp b/src/dawn/wire/client/Buffer.cpp index fcfebbd..df97863 100644 --- a/src/dawn/wire/client/Buffer.cpp +++ b/src/dawn/wire/client/Buffer.cpp
@@ -315,27 +315,29 @@ } void Buffer::WillDropLastExternalRef() { - mState.Use([this](auto state) { - SetFutureStatus(state, WGPUMapAsyncStatus_Aborted, - "Buffer was destroyed before mapping was resolved."); - }); + SetFutureStatus(WGPUMapAsyncStatus_Aborted, + "Buffer was destroyed before mapping was resolved."); } ObjectType Buffer::GetObjectType() const { return ObjectType::Buffer; } -void Buffer::SetFutureStatus(GuardedState& state, - WGPUMapAsyncStatus status, - std::string_view message) { - if (!state->pendingMapRequest) { +void Buffer::SetFutureStatus(WGPUMapAsyncStatus status, std::string_view message) { + auto futureID = mState.Use([&](auto state) -> std::optional<FutureID> { + if (!state->pendingMapRequest) { + return std::nullopt; + } + + FutureID result = state->pendingMapRequest->futureID; + state->pendingMapRequest = std::nullopt; + return result; + }); + + if (!futureID) { return; } - - FutureID futureID = state->pendingMapRequest->futureID; - state->pendingMapRequest = std::nullopt; - - auto wireStatus = GetEventManager().SetFutureReady<MapAsyncEvent>(futureID, status, + auto wireStatus = GetEventManager().SetFutureReady<MapAsyncEvent>(*futureID, status, ToOutputStringView(message)); DAWN_CHECK(wireStatus == WireResult::Success); } @@ -353,9 +355,6 @@ bool success = mState.Use([&](auto state) { if (state->pendingMapRequest) { - [[maybe_unused]] auto id = GetEventManager().SetFutureReady<MapAsyncEvent>( - futureIDInternal, WGPUMapAsyncStatus_Error, - ToOutputStringView("Buffer already has an outstanding map pending.")); return false; } @@ -380,6 +379,9 @@ return true; }); if (!success) { + [[maybe_unused]] auto id = GetEventManager().SetFutureReady<MapAsyncEvent>( + futureIDInternal, WGPUMapAsyncStatus_Error, + ToOutputStringView("Buffer already has an outstanding map pending.")); return {futureIDInternal}; } @@ -508,11 +510,10 @@ state->mappedState = MapState::Unmapped; state->mappedOffset = 0; state->mappedSize = 0; - - SetFutureStatus(state, WGPUMapAsyncStatus_Aborted, - "Buffer was unmapped before mapping was resolved."); }); + SetFutureStatus(WGPUMapAsyncStatus_Aborted, "Buffer was unmapped before mapping was resolved."); + BufferUnmapCmd cmd{}; cmd.self = ToAPI(this); client->SerializeCommand(cmd); @@ -523,10 +524,10 @@ // Remove the current mapping and destroy MemoryHandle. mState.Use([&](auto state) { - SetFutureStatus(state, WGPUMapAsyncStatus_Aborted, - "Buffer was destroyed before mapping was resolved."); FreeMappedData(state); }); + SetFutureStatus(WGPUMapAsyncStatus_Aborted, + "Buffer was destroyed before mapping was resolved."); BufferDestroyCmd cmd{}; cmd.self = ToAPI(this);
diff --git a/src/dawn/wire/client/Buffer.h b/src/dawn/wire/client/Buffer.h index ccacc8c..a2d5dbd 100644 --- a/src/dawn/wire/client/Buffer.h +++ b/src/dawn/wire/client/Buffer.h
@@ -116,8 +116,8 @@ void WillDropLastExternalRef() override; - // Prepares the callbacks to be called and potentially calls them - void SetFutureStatus(GuardedState& state, WGPUMapAsyncStatus status, std::string_view message); + // Prepares the callbacks to be called and potentially calls them. + void SetFutureStatus(WGPUMapAsyncStatus status, std::string_view message); void FreeMappedData(GuardedState& state);