More fixes for signed integer overflow.
Fence.cpp: My previous fix to the fix was insufficient because a signed integer overflow could still occur as follows (this was observed in an internal test at Google). If the conditional on line 87 is true, then a clamped value is passed into `wait`, which causes the conditional on line 133 to fail, which causes `wait_for` to be called inappropriately, which is where an overflow would occur. MetalHandles.mm: This is more theoretical, but to prevent potential integer overflow within STL, I think we should call `wait()` rather than `wait_for()` when an infinite timeout is desired. This is our fourth fix to fences in since November 2; see alsodcca236,e9c9e45, and8969416. :)
This commit is contained in:
@@ -849,12 +849,13 @@ void MetalFence::onSignal(MetalFenceSignalBlock block) {
|
||||
|
||||
FenceStatus MetalFence::wait(uint64_t timeoutNs) {
|
||||
if (@available(macOS 10.14, iOS 12, *)) {
|
||||
using ns = std::chrono::nanoseconds;
|
||||
std::unique_lock<std::mutex> guard(state->mutex);
|
||||
timeoutNs = std::min(timeoutNs, (uint64_t) std::chrono::nanoseconds::max().count());
|
||||
while (state->status == FenceStatus::TIMEOUT_EXPIRED) {
|
||||
if (timeoutNs == 0 ||
|
||||
state->cv.wait_for(guard, std::chrono::nanoseconds(timeoutNs)) ==
|
||||
std::cv_status::timeout) {
|
||||
if (timeoutNs == FENCE_WAIT_FOR_EVER) {
|
||||
state->cv.wait(guard);
|
||||
} else if (timeoutNs == 0 ||
|
||||
state->cv.wait_for(guard, ns(timeoutNs)) == std::cv_status::timeout) {
|
||||
return FenceStatus::TIMEOUT_EXPIRED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +71,6 @@ FenceStatus FFence::waitAndDestroy(FFence* fence, Mode mode) noexcept {
|
||||
UTILS_NOINLINE
|
||||
FenceStatus FFence::wait(Mode mode, uint64_t timeout) noexcept {
|
||||
ASSERT_PRECONDITION(UTILS_HAS_THREADING || timeout == 0, "Non-zero timeout requires threads.");
|
||||
const bool waitForever = timeout == FENCE_WAIT_FOR_EVER;
|
||||
timeout = std::min(timeout, (uint64_t) ns::max().count());
|
||||
|
||||
FEngine& engine = mEngine;
|
||||
|
||||
@@ -98,7 +96,7 @@ FenceStatus FFence::wait(Mode mode, uint64_t timeout) noexcept {
|
||||
}
|
||||
engine.pumpPlatformEvents();
|
||||
const auto elapsed = std::chrono::system_clock::now() - startTime;
|
||||
if (!waitForever && elapsed >= ns(timeout)) {
|
||||
if (timeout != FENCE_WAIT_FOR_EVER && elapsed >= ns(timeout)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user