Tcl_LimitCheck(3tcl)

πŸ’– Tcl_LimitCheck β€” the Tcl Library Procedures glow-up πŸ’–

okay bestie, so this one is Tcl_LimitCheck(3tcl) from the Tcl Library Procedures and it's literally the whole ✨resource limits✨ subsystem for interpreters. it's giving "let me put a leash on this script before it eats my whole CPU" and honestly? iconic. πŸŽ€


✨ NAME ✨

Tcl_LimitAddHandler, Tcl_LimitCheck, Tcl_LimitExceeded, Tcl_LimitGetCommands, Tcl_LimitGetGranularity, Tcl_LimitGetTime, Tcl_LimitReady, Tcl_LimitRemoveHandler, Tcl_LimitSetCommands, Tcl_LimitSetGranularity, Tcl_LimitSetTime, Tcl_LimitTypeEnabled, Tcl_LimitTypeExceeded, Tcl_LimitTypeReset, Tcl_LimitTypeSet β€” manage and check resource limits on interpreters 🫢


✨ SYNOPSIS ✨

#include <tcl.h>

int
Tcl_LimitCheck(interp)

int
Tcl_LimitReady(interp)

int
Tcl_LimitExceeded(interp)

int
Tcl_LimitTypeExceeded(interp, type)

int
Tcl_LimitTypeEnabled(interp, type)

Tcl_LimitTypeSet(interp, type)

Tcl_LimitTypeReset(interp, type)

Tcl_Size
Tcl_LimitGetCommands(interp)

Tcl_LimitSetCommands(interp, commandLimit)

Tcl_LimitGetTime(interp, timeLimitPtr)

Tcl_LimitSetTime(interp, timeLimitPtr)

int
Tcl_LimitGetGranularity(interp, type)

Tcl_LimitSetGranularity(interp, type, granularity)

Tcl_LimitAddHandler(interp, type, handlerProc, clientData, deleteProc)

Tcl_LimitRemoveHandler(interp, type, handlerProc, clientData)

✨ ARGUMENTS ✨

  • Tcl_Interp *interp (in) β€” the interpreter that the limit being managed applies to, or the one that's about to get its limits checked. it's the main character here πŸ’…
  • int type (in) β€” which kind of limit the operation is talking about. it must be either TCL_LIMIT_COMMANDS or TCL_LIMIT_TIME. no third option, bestie, that's the whole list.
  • Tcl_Size commandLimit (in) β€” the max number of commands that may be executed in the interpreter (counted the way info cmdcount reports it). so like, the vibe ceiling. 🌸
  • Tcl_Time *timeLimitPtr (in/out) β€” a pointer to a struct that either gets the new time limit read from it (Tcl_LimitSetTime) or gets the current time limit written to it (Tcl_LimitGetTime). yes it swings both ways, we love a versatile king πŸ‘‘
  • int granularity (in) β€” a divisor saying how often a particular limit should actually get checked. must be at least 1. (zero would be a crime, do not.) 😭
  • Tcl_LimitHandlerProc *handlerProc (in) β€” the function to call when a particular limit is exceeded. and here's the juicy part: if the handlerProc removes or raises the limit while it's running, the limited interpreter is allowed to keep on processing after the handler returns. also, you can attach many handlers to the same interpreter limit β€” their order of execution is not defined, and they have to be identified by handlerProc and clientData when you delete them. so keep receipts, fr fr πŸ“
  • void *clientData (in) β€” an arbitrary pointer-sized word used to pass some context to the handlerProc function. the little handbag of extra info. πŸŽ€
  • Tcl_LimitHandlerDeleteProc *deleteProc (in) β€” the function to call whenever a handler gets deleted. it may be NULL if the clientData doesn't need any deletion. πŸ’€

✨ DESCRIPTION ✨

Tcl's interpreter resource limit subsystem lets you keep close control over how much computation time a script is allowed to use. it's super useful when a program is split into multiple pieces and some pieces are more trusted than others (think: web application servers πŸ‘€). some parts get the keys to the house, some parts get a timer. 🌈

Every interpreter can have a limit on the wall-time for execution, and a limit on the number of commands the interpreter may execute. but here's the thing β€” checking these limits is potentially expensive (especially the time limit, she's high maintenance πŸ’…). so each limit also has a checking granularity, which is a divisor for an internal count of the number of points in the core where a check may be performed. and where are those points? immediately before executing a command, and at an unspecified frequency between running commands (which can happen in empty-bodied while loops β€” sneaky little things). πŸ¦‹

The final component of the limit engine is a callback scheme, which lets you get notified when a limit has been exceeded. these callbacks can just do some logging, or they can allocate more resources to the interpreter so it's permitted to keep processing longer. generous queen behavior. πŸ’–

When a limit is exceeded (and the callbacks have run β€” and reminder, the order the callbacks run in is unspecified), execution in the limited interpreter is stopped by raising an error and setting a flag that prevents the catch command in that interpreter from trapping that error. so catch can't save you here, bestie, it's blocked. 😀 it's up to the context that started execution in that interpreter (typically the main interpreter) to handle the error.


✨ LIMIT CHECKING API ✨

To check the resource limits for an interpreter, call Tcl_LimitCheck. it returns TCL_OK if the limit was not exceeded (after processing callbacks), and TCL_ERROR if the limit was exceeded β€” in which case an error message also gets placed in the interpreter result. πŸ“¬

but babes, only call that function when Tcl_LimitReady returns non-zero, so the granularity policy is enforced. that's the rule. 🚨

this API is designed to be similar in usage to Tcl_AsyncReady and Tcl_AsyncInvoke, iykyk.

When you're writing code that might behave like catch with respect to errors, you should only trap an error if Tcl_LimitExceeded returns zero. if it returns non-zero, the interpreter is in a limit-exceeded state and errors should be allowed to propagate to the calling context. let it go, let it flow, do not intercept. 🌊 you can also check whether a particular type of limit has been exceeded using Tcl_LimitTypeExceeded.


✨ LIMIT CONFIGURATION ✨

To check whether a limit has been set (not whether it's actually been exceeded β€” different thing, bestie) on an interpreter, call Tcl_LimitTypeEnabled with the type of limit you want to check.

  • to enable a particular limit, call Tcl_LimitTypeSet
  • to disable a limit, call Tcl_LimitTypeReset

The level of a command limit can be set using Tcl_LimitSetCommands, and retrieved using Tcl_LimitGetCommands. same deal for a time limit with Tcl_LimitSetTime and Tcl_LimitGetTime respectively β€” except with that API, the time limit is copied from and to the Tcl_Time structure that the timeLimitPtr argument points to. struct handoff, love that for us. 🫱

The checking granularity for a particular limit can be set using Tcl_LimitSetGranularity and retrieved using Tcl_LimitGetGranularity.

note: granularities must always be positive. always. no exceptions. ✨

🌸 LIMIT CALLBACKS 🌸

To add a handler callback that gets invoked when a limit is exceeded, call Tcl_LimitAddHandler. the handlerProc argument describes the function that will actually be called, and it should have this prototype:

typedef void Tcl_LimitHandlerProc(
        void *clientData,
        Tcl_Interp *interp);

The clientData argument that gets passed to the handler will be whatever you passed to the clientData argument of Tcl_LimitAddHandler, and the interp is the interpreter that had its limit exceeded. πŸ’…

The deleteProc argument to Tcl_LimitAddHandler is a function to call in order to delete the clientData value. it may be:

  • TCL_STATIC or NULL if no deletion action is necessary
  • TCL_DYNAMIC if all that's necessary is to free the structure with Tcl_Free

otherwise, it should refer to a function with this prototype:

typedef void Tcl_LimitHandlerDeleteProc(
        void *clientData);

A limit handler may be deleted using Tcl_LimitRemoveHandler. the handler removed will be the first one found (out of the handlers added with Tcl_LimitAddHandler) with exactly matching type, handlerProc and clientData arguments. first come, first yeeted. πŸ’€ this function always invokes the deleteProc on the clientData β€” unless the deleteProc was NULL or TCL_STATIC.

✨ KEYWORDS ✨

okay bestie, final section, and it's literally just the vibe tags for this page β€” the little search terms so future you (or man -k) can find it again when your brain is mush πŸ’…

  • interpreter 🌸
  • resource πŸ’–
  • limit πŸŽ€
  • commands ✨
  • time ⏰
  • callback 🫢

that's the whole list, no cap. six words, all of them doing their little search-engine job so this page doesn't get lost in the void πŸ™ˆ


and that's a wrap on Tcl_LimitCheck(3tcl), bestie πŸŽ‰ you made it to the end of the whole page β€” go set some limits, protect your interpreter, and slay responsibly πŸ‘‘πŸ’–

this page shipped with Tcl 8.5 β€” yes, 8.5, she's an icon and she's been iconic πŸ¦‹ mwah, see you in the next manpage ⭐

πŸ“¦ where this page comes from