mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (Pipe): the device-loss debug knob re-arms when set to a new value.
This commit is contained in:
@@ -186,9 +186,22 @@ namespace MobileGL::MG_Pipe {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (at <= 0) return false;
|
||||
static std::atomic<long> armedAt{0};
|
||||
static std::atomic<long> seen{0};
|
||||
static std::atomic<bool> fired{false};
|
||||
if (at <= 0) {
|
||||
// Unset (or 0) disarms: the same value set again counts afresh.
|
||||
if (armedAt.load(std::memory_order_relaxed) != 0) armedAt.store(0, std::memory_order_relaxed);
|
||||
return false;
|
||||
}
|
||||
// A NEW VALUE RE-ARMS. One server process outlives many sessions, so a second loss is
|
||||
// injected by setting the knob again (another value, or 0 and then a value): the count
|
||||
// restarts from the checks made after it was seen.
|
||||
if (long previous = armedAt.load(std::memory_order_acquire);
|
||||
previous != at && armedAt.compare_exchange_strong(previous, at, std::memory_order_acq_rel)) {
|
||||
seen.store(0, std::memory_order_release);
|
||||
fired.store(false, std::memory_order_release);
|
||||
}
|
||||
if (fired.load(std::memory_order_acquire)) return false;
|
||||
if (seen.fetch_add(1, std::memory_order_acq_rel) + 1 < at) return false;
|
||||
if (fired.exchange(true, std::memory_order_acq_rel)) return false;
|
||||
|
||||
@@ -119,8 +119,10 @@ namespace MobileGL::MG_Pipe {
|
||||
// A DEBUG KNOB THAT MAKES ONE DEVICE CHECK REPORT A LOSS, so the containment above can be
|
||||
// driven without a GPU that faults on demand. MOBILEGL_DEBUG_INJECT_DEVICE_LOST_AT=N (or, on
|
||||
// Android, the property debug.mobilegl.inject_device_lost_at) makes the N-th device check the
|
||||
// backends make after the knob was first seen nonzero answer "lost", once per process. The
|
||||
// backends ask at their frame boundaries and readbacks; unset (the default) it is one getenv.
|
||||
// backends make after the knob was first seen nonzero answer "lost", once per value: setting
|
||||
// another value (or 0 and then a value again) re-arms it, so one server process can lose
|
||||
// several sessions in turn. The backends ask at their frame boundaries and readbacks; unset
|
||||
// (the default) it is one getenv.
|
||||
bool MGPipeDebugDeviceLossDue();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -250,3 +250,33 @@ TEST(FatalFunnelSeam, ADeviceLossWithNoArmedSessionDiesThroughSessionFail) {
|
||||
<< "an unarmed device loss must keep the inproc shape's death";
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
// THE DEBUG KNOB RE-ARMS ON A NEW VALUE. One server process serves many sessions, so a device test
|
||||
// that loses a second session in the same process sets the knob again. Each value fires once, at its
|
||||
// N-th check; the same value set again after 0 counts afresh. In a death-test child, so the knob's
|
||||
// process-wide counters start at zero. Red with the old once-per-process latch: the second value
|
||||
// never fires (exit code 2).
|
||||
TEST(FatalFunnelSeam, TheDeviceLossKnobFiresOncePerValueAndReArmsOnANewOne) {
|
||||
EXPECT_EXIT(
|
||||
{
|
||||
const auto checks = [](int n) {
|
||||
int fired = 0;
|
||||
for (int i = 0; i < n; ++i) fired += MobileGL::MG_Pipe::MGPipeDebugDeviceLossDue() ? 1 << i : 0;
|
||||
return fired;
|
||||
};
|
||||
::unsetenv("MOBILEGL_DEBUG_INJECT_DEVICE_LOST_AT");
|
||||
if (checks(3) != 0) std::_Exit(1);
|
||||
::setenv("MOBILEGL_DEBUG_INJECT_DEVICE_LOST_AT", "2", 1);
|
||||
if (checks(4) != 0b0010) std::_Exit(1); // the 2nd check only, then never again
|
||||
::setenv("MOBILEGL_DEBUG_INJECT_DEVICE_LOST_AT", "1", 1);
|
||||
if (checks(3) != 0b001) std::_Exit(2); // a new value re-arms
|
||||
::setenv("MOBILEGL_DEBUG_INJECT_DEVICE_LOST_AT", "0", 1);
|
||||
if (checks(2) != 0) std::_Exit(3);
|
||||
::setenv("MOBILEGL_DEBUG_INJECT_DEVICE_LOST_AT", "1", 1);
|
||||
if (checks(2) != 0b01) std::_Exit(4); // 0 then the same value again re-arms too
|
||||
std::_Exit(0);
|
||||
},
|
||||
::testing::ExitedWithCode(0), "");
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user