diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 6c6a9b553c8..4b1b9fcf3d1 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -211,6 +211,15 @@ A.flags_1 &= ~OVERLAY_QUEUED_1;\ } +/** + Create a new timer and add it to the queue. + * Arguments: + * * callback the callback to call on timer finish + * * wait deciseconds to run the timer for + * * flags flags for this timer, see: code\__DEFINES\subsystems.dm +*/ +#define addtimer(args...) _addtimer(args, file = __FILE__, line = __LINE__) + // Air subsystem subtasks #define SSAIR_PIPENETS 1 #define SSAIR_ATMOSMACHINERY 2 diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index be77190e418..af5e7c604d8 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -316,6 +316,8 @@ SUBSYSTEM_DEF(timer) var/timeToRun var/wait var/hash + /// The source of the timedevent, whatever called addtimer + var/source var/list/flags var/spent = 0 //time we ran the timer. var/name //for easy debugging. @@ -323,13 +325,14 @@ SUBSYSTEM_DEF(timer) var/datum/timedevent/next var/datum/timedevent/prev -/datum/timedevent/New(datum/callback/callBack, wait, flags, hash) +/datum/timedevent/New(datum/callback/callBack, wait, flags, hash, source) var/static/nextid = 1 id = TIMER_ID_NULL src.callBack = callBack src.wait = wait src.flags = flags src.hash = hash + src.source = source if (flags & TIMER_CLIENT_TIME) timeToRun = REALTIMEOFDAY + wait @@ -456,14 +459,15 @@ SUBSYSTEM_DEF(timer) . = "[callBack.object.type]" /** - * Create a new timer and insert it in the queue + * Create a new timer and insert it in the queue. + * You should not call this directly, and should instead use the addtimer macro, which includes source information. * * Arguments: * * callback the callback to call on timer finish * * wait deciseconds to run the timer for * * flags flags for this timer, see: code\__DEFINES\subsystems.dm */ -/proc/addtimer(datum/callback/callback, wait = 0, flags = 0) +/proc/_addtimer(datum/callback/callback, wait = 0, flags = 0, file, line) if (!callback) CRASH("addtimer called without a callback") @@ -504,7 +508,7 @@ SUBSYSTEM_DEF(timer) else if(flags & TIMER_OVERRIDE) stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE") - var/datum/timedevent/timer = new(callback, wait, flags, hash) + var/datum/timedevent/timer = new(callback, wait, flags, hash, file && "[file]:[line]") return timer.id /** diff --git a/code/game/objects/effects/spawners/xeno_egg_delivery.dm b/code/game/objects/effects/spawners/xeno_egg_delivery.dm index feb5605342c..d0e99d0f903 100644 --- a/code/game/objects/effects/spawners/xeno_egg_delivery.dm +++ b/code/game/objects/effects/spawners/xeno_egg_delivery.dm @@ -15,5 +15,5 @@ message_admins("An alien egg has been delivered to [ADMIN_VERBOSEJMP(T)].") log_game("An alien egg has been delivered to [AREACOORD(T)]") var/message = "Attention [station_name()], we have entrusted you with a research specimen in [get_area_name(T, TRUE)]. Remember to follow all safety precautions when dealing with the specimen." - SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, CALLBACK(GLOBAL_PROC, /proc/print_command_report, message), announcement_time)) + SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/_addtimer, CALLBACK(GLOBAL_PROC, /proc/print_command_report, message), announcement_time)) return INITIALIZE_HINT_QDEL diff --git a/code/game/world.dm b/code/game/world.dm index dc31e2a9318..2e9bc3380f5 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -95,7 +95,7 @@ GLOBAL_VAR(restart_counter) #else cb = VARSET_CALLBACK(SSticker, force_ending, TRUE) #endif - SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS)) + SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/_addtimer, cb, 10 SECONDS)) /world/proc/SetupExternalRSC() #if (PRELOAD_RSC == 0) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 5dfedf37d35..95df5628846 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -174,6 +174,7 @@ GLOBAL_PROTECT(admin_verbs_debug) /datum/admins/proc/view_refs, /datum/admins/proc/view_del_failures, #endif + /client/proc/check_timer_sources ) GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release)) GLOBAL_PROTECT(admin_verbs_possess) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 3d8ad9fa0fd..2677bdc82e0 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -889,3 +889,63 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that return if(alert(usr, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modificatoins?", "Really reset?", "No", "Yes") == "Yes") config.admin_reload() + +/// A debug verb to check the sources of currently running timers +/client/proc/check_timer_sources() + set category = "Debug" + set name = "Check Timer Sources" + set desc = "Checks the sources of the running timers" + if (!check_rights(R_DEBUG)) + return + + var/bucket_list_output = generate_timer_source_output(SStimer.bucket_list) + var/second_queue = generate_timer_source_output(SStimer.second_queue) + + usr << browse({" +
| [timer_data["source"]] | +[timer_data["count"]] | +