diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index d9db6e89a2..71dbf82734 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -8,6 +8,7 @@ #define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste. #define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm. //if TESTING is enabled, qdel will call this object's find_references() verb. +#define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails. //defines for the gc_destroyed var #define GC_QUEUE_PREQUEUE 1 diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 130186c928..d0e4e1f74d 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -25,6 +25,10 @@ SUBSYSTEM_DEF(garbage) //Queue var/list/queues + #ifdef TESTING + var/list/reference_find_on_fail = list() + #endif + /datum/controller/subsystem/garbage/PreInit() queues = new(GC_QUEUE_COUNT) @@ -152,6 +156,9 @@ SUBSYSTEM_DEF(garbage) ++gcedlasttick ++totalgcs pass_counts[level]++ + #ifdef TESTING + reference_find_on_fail -= refID //It's deleted we don't care anymore. + #endif if (MC_TICK_CHECK) break continue @@ -160,8 +167,14 @@ SUBSYSTEM_DEF(garbage) fail_counts[level]++ switch (level) if (GC_QUEUE_CHECK) + #ifdef TESTING + if(reference_find_on_fail[refID]) + D.find_references() #ifdef GC_FAILURE_HARD_LOOKUP - D.find_references() + else + D.find_references() + #endif + reference_find_on_fail -= refID #endif var/type = D.type var/datum/qdel_item/I = items[type] @@ -261,6 +274,11 @@ SUBSYSTEM_DEF(garbage) /datum/qdel_item/New(mytype) name = "[mytype]" +#ifdef TESTING +/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE) + SSgarbage.reference_find_on_fail[REF(D)] = TRUE + qdel(D, force) +#endif // Should be treated as a replacement for the 'del' keyword. // Datums passed to this will be given a chance to clean up references to allow the GC to collect them. @@ -318,6 +336,11 @@ SUBSYSTEM_DEF(garbage) #ifdef TESTING D.find_references() #endif + if (QDEL_HINT_IFFAIL_FINDREFERENCE) + SSgarbage.PreQueue(D) + #ifdef TESTING + SSgarbage.reference_find_on_fail[REF(D)] = TRUE + #endif else #ifdef TESTING if(!I.no_hint) @@ -387,10 +410,17 @@ SUBSYSTEM_DEF(garbage) set name = "qdel() then Find References" set src in world - qdel(src) + qdel(src, TRUE) //Force. if(!running_find_references) find_references(TRUE) +/datum/verb/qdel_then_if_fail_find_references() + set category = "Debug" + set name = "qdel() then Find References if GC failure" + set src in world + + qdel_and_find_ref_if_fail(src, TRUE) + /datum/proc/DoSearchVar(X, Xname, recursive_limit = 64) if(usr && usr.client && !usr.client.running_find_references) return