From e33577856c2c994bcffaae132586404e7bf4e4a0 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Wed, 22 Dec 2021 15:48:24 +0100 Subject: [PATCH] [MIRROR] Fix: potential bucket corruption in timer reset_buckets [MDB IGNORE] (#10156) * Fix: potential bucket corruption in timer reset_buckets (#63427) Ports Semoro's fix (ss220-space/Paradise#511) related to potential SStimer bucket corruption which caused infinite loop. The essence of the fix is that earlier timers with a built linkedlist could get into the second queue, which could cause an incorrect state. It works super stupidly, resets the state to the original correct one BUT THERE IS STILL A BUG IN THE CODE RELATED TO THE INFINITE LOOP! For some reason the SStimer on our server started to break recently at the beginning of the round. Found that code for waterfall drip effect was causing the issue. Found that setting frequensy to 0 (and calling reset_bucket sometimes) can be used to reproduce the bug. Tried to fix it with this PR there is an oustanding bug with airlocks causing SStimer to brake sometimes. cl fix: fixed potential bucket corruption in timer reset_buckets /cl * Fix: potential bucket corruption in timer reset_buckets Co-authored-by: Aziz Chynaliev --- code/controllers/subsystem/timer.dm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index f4f3f601ffd..81ddc55aead 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -260,6 +260,12 @@ SUBSYSTEM_DEF(timer) // Add all timed events from the secondary queue as well alltimers += second_queue + for (var/datum/timedevent/t as anything in alltimers) + t.bucket_joined = FALSE + t.bucket_pos = -1 + t.prev = null + t.next = null + // If there are no timers being tracked by the subsystem, // there is no need to do any further rebuilding if (!length(alltimers)) @@ -303,6 +309,7 @@ SUBSYSTEM_DEF(timer) new_bucket_count++ var/bucket_pos = BUCKET_POS(timer) timer.bucket_pos = bucket_pos + timer.bucket_joined = TRUE var/datum/timedevent/bucket_head = bucket_list[bucket_pos] if (!bucket_head)