diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index d04e40311ce2..ab2bd38217d6 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -352,3 +352,5 @@ #define SSLIQUIDS_RUN_TYPE_OCEAN 6 #define SSLIQUIDS_RUN_TYPE_TEMPERATURE 7 #define SSLIQUIDS_RUN_TYPE_CACHED_EDGES 8 + +#define ENQUEUE_SANITY 10000 diff --git a/code/__DEFINES/~monkestation/logging.dm b/code/__DEFINES/~monkestation/logging.dm index 3ecc13c91064..7862616789ad 100644 --- a/code/__DEFINES/~monkestation/logging.dm +++ b/code/__DEFINES/~monkestation/logging.dm @@ -1,2 +1,3 @@ #define LOG_CATEGORY_GAME_LOOC "game-looc" #define LOG_CATEGORY_STORYTELLER "storyteller" +#define LOG_CATEGORY_ENQUEUE "enqueue" diff --git a/code/__DEFINES/~monkestation/maths.dm b/code/__DEFINES/~monkestation/maths.dm new file mode 100644 index 000000000000..04901dc4e387 --- /dev/null +++ b/code/__DEFINES/~monkestation/maths.dm @@ -0,0 +1 @@ +#define RELATIVE_ERROR(actual, expected) (abs(actual - expected) / expected) diff --git a/code/__HELPERS/logging/debug.dm b/code/__HELPERS/logging/debug.dm index 61b686811c89..de0900a23912 100644 --- a/code/__HELPERS/logging/debug.dm +++ b/code/__HELPERS/logging/debug.dm @@ -59,3 +59,6 @@ logger.Log(LOG_CATEGORY_RUNTIME, text, data) #endif SEND_TEXT(world.log, text) + +/proc/log_enqueue(text, list/data) + logger.Log(LOG_CATEGORY_ENQUEUE, text, data) diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 2e122535fe46..f4b628fe1f14 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -106,6 +106,10 @@ /// Previous subsystem in the queue of subsystems to run this tick var/datum/controller/subsystem/queue_prev + var/avg_iter_count = 0 + var/avg_drift = 0 + var/list/enqueue_log = list() + //Do not blindly add vars here to the bottom, put it where it goes above //If your var only has two values, put it in as a flag. @@ -191,10 +195,38 @@ var/queue_node_priority var/queue_node_flags + var/iter_count = 0 + + enqueue_log.Cut() for (queue_node = Master.queue_head; queue_node; queue_node = queue_node.queue_next) + iter_count++ + if(iter_count >= ENQUEUE_SANITY) + var/msg = "[src] subsystem has likely entered an infinite enqueue loop, restarting MC immediately!" + to_chat_immediate( + GLOB.admins, + examine_block(span_userdanger("ERROR: [msg]")), + type = MESSAGE_TYPE_DEBUG + ) + log_enqueue(msg, list("enqueue_log" = enqueue_log.Copy())) +#if defined(INIT_ORDER_PLEXORA) && !defined(UNIT_TESTS) + SSplexora.mc_alert("[src] has likely entered an infinite loop in enqueue(), we're restarting the MC immediately!") +#endif + stack_trace("enqueue() entered an infinite loop, we're restarting the MC!") + enqueue_log.Cut() + Recreate_MC() + return + + queue_node_priority = queue_node.queued_priority queue_node_flags = queue_node.flags + enqueue_log["[iter_count]"] = list( + "node" = "[queue_node]", + "next" = "[queue_node.queue_next || "(none)"]", + "priority" = queue_node_priority, + "flags" = queue_node_flags, + ) + if (queue_node_flags & (SS_TICKER|SS_BACKGROUND) == SS_TICKER) if ((SS_flags & (SS_TICKER|SS_BACKGROUND)) != SS_TICKER) continue @@ -215,6 +247,11 @@ if (queue_node_priority < SS_priority) break + if(iter_count > 0) + avg_iter_count = avg_iter_count ? ((avg_iter_count + iter_count) * 0.5) : iter_count + var/drift = RELATIVE_ERROR(iter_count, avg_iter_count) + avg_drift = avg_drift ? ((drift + avg_drift) * 0.5) : drift + queued_time = world.time queued_priority = SS_priority state = SS_QUEUED @@ -325,5 +362,7 @@ out["relation_id_SS"] = "[ss_id]-[time_stamp()]-[rand(100, 10000)]" // since we insert custom into its own table we want to add a relational id to fetch from the custom data and the subsystem out["cost"] = cost out["tick_usage"] = tick_usage + out["avg_iter_count"] = avg_iter_count + out["avg_drift"] = avg_drift out["custom"] = list() // Override as needed on child return out diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 2d3a452fdec5..22cbf7824c3d 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -172,17 +172,18 @@ SUBSYSTEM_DEF(statpanels) for(var/image/target_image as anything in target.images) if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override) continue - overrides += target_image.loc + overrides[target_image.loc] = TRUE var/list/atoms_to_display = list(target_mob.listed_turf) + var/should_check_obscured = (length(target_mob.listed_turf?.contents) < 25) for(var/atom/movable/turf_content as anything in target_mob.listed_turf) if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) continue if(turf_content.invisibility > target_mob.see_invisible) continue - if(turf_content in overrides) + if(overrides[turf_content]) continue - if(turf_content.IsObscured()) + if(should_check_obscured && turf_content.IsObscured()) continue atoms_to_display += turf_content diff --git a/monkestation/code/__HELPERS/files.dm b/monkestation/code/__HELPERS/files.dm index be454635ab42..25ea7c4537a7 100644 --- a/monkestation/code/__HELPERS/files.dm +++ b/monkestation/code/__HELPERS/files.dm @@ -1,4 +1,4 @@ -/client/proc/browse_files(root_type = BROWSE_ROOT_ALL_LOGS, max_iterations = 10, list/valid_extensions = list("txt", "log", "htm", "html", "gz", "json"), list/whitelist = null, allow_folder = TRUE) +/client/proc/browse_files(root_type = BROWSE_ROOT_ALL_LOGS, max_iterations = 10, list/valid_extensions = list("txt", "log", "htm", "html", "gz", "json", "log.json"), list/whitelist = null, allow_folder = TRUE) var/regex/valid_ext_regex = new("\\.(?:[regex_quote_list(valid_extensions)])$", "i") var/regex/whitelist_regex if(whitelist) diff --git a/monkestation/code/modules/logging/categories/log_category_debug.dm b/monkestation/code/modules/logging/categories/log_category_debug.dm new file mode 100644 index 000000000000..dd98fa011d25 --- /dev/null +++ b/monkestation/code/modules/logging/categories/log_category_debug.dm @@ -0,0 +1,3 @@ +/datum/log_category/debug_enqueue + category = LOG_CATEGORY_ENQUEUE + debugger_visible = TRUE diff --git a/tgstation.dme b/tgstation.dme index 57986e06964a..b89624c94c00 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -437,6 +437,7 @@ #include "code\__DEFINES\~monkestation\market.dm" #include "code\__DEFINES\~monkestation\martial_arts.dm" #include "code\__DEFINES\~monkestation\materials.dm" +#include "code\__DEFINES\~monkestation\maths.dm" #include "code\__DEFINES\~monkestation\mecha.dm" #include "code\__DEFINES\~monkestation\microfusion.dm" #include "code\__DEFINES\~monkestation\misc.dm" @@ -7135,6 +7136,7 @@ #include "monkestation\code\modules\loafing\code\loafer.dm" #include "monkestation\code\modules\logging\log_category.dm" #include "monkestation\code\modules\logging\log_holder.dm" +#include "monkestation\code\modules\logging\categories\log_category_debug.dm" #include "monkestation\code\modules\logging\categories\log_category_game.dm" #include "monkestation\code\modules\map_gen_expansions\_basemapping.dm" #include "monkestation\code\modules\map_gen_expansions\areas.dm"