Mutant limits reference
This document is generated by go run ./cmd/gendocs from the source tree. Do not edit it by hand; edit the constant's doc comment and regenerate.
This document is generated by go run ./cmd/gendocs from the source tree. Do not edit it by hand;
edit the constant's doc comment and regenerate. go run ./cmd/gendocs -check fails when it is out of date.
A value that bounds what Mutant will do -- how much it reads, how deep it
recurses, how long it waits, how many entries it keeps -- belongs in a named
constant in the package that enforces it, marked with a //mutant:limit <unit> directive and
a written reason. These are those constants. A limit that a command-line flag can
change names the flag; nothing here is read from the environment or from a
configuration file (see CONFIGURATION_POLICY.md).
go test ./policy/ finds limits by their shape and their name -- a literal
allocation size, a literal timeout, a depth compared with a number, a constant
called max... with no directive -- and fails on any it finds that is neither
listed here nor held, one entry at a time, in policy/limit_budget.go. A limit
written in a shape the guard does not recognise is in neither place. Values fixed
by a file format or a protocol are not limits; they are marked //mutant:format
and are not listed.
74 limits in 8 packages bound a run. 4 limits in 2 packages bound the tools around it. The guard finds 115 limits that are not named yet; policy/limit_budget.go lists each one.
`builtin`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
defaultSearchContext |
32 bytes | bytes | -- | defaultSearchContext is how much plaintext a hit hands back on each side of the match unless the search asks otherwise: about a line, which is enough to recognise what was found. | builtin/record_search.go |
defaultSearchHits |
100 | count | -- | defaultSearchHits is how many hits a search hands back unless it asks for more or fewer. Every match is counted whatever this is. | builtin/record_search.go |
httpHeadReadSlack |
4 KiB | bytes | -- | httpHeadReadSlack is what the socket is allowed beyond maxHTTPHeaderBytes while a head is being read. The parser draws through a bufio.Reader, which fills a whole buffer at a time, so the last fill can legitimately carry the start of a body past the end of the head. The figure is one bufio buffer, which is what net/http's own server adds to MaxHeaderBytes for this reason. | builtin/mitm_http.go |
httpIdleConnTimeout |
1m30s | duration | -- | httpIdleConnTimeout is how long a connection kept for reuse waits for the next request before it is closed. | builtin/http.go |
httpMaxIdleConns |
100 | count | -- | httpMaxIdleConns is how many connections, across every host, are kept for reuse. | builtin/http.go |
httpMaxRedirects |
10 | count | -- | httpMaxRedirects bounds how many redirects one http_get, http_post or http_request follows. It is ten, which is what net/http's own defaultCheckRedirect stops after -- and that default is one in the strict sense, because a CheckRedirect of our own replaces it outright rather than adding to it. So the number has to be named here: checkHTTPRedirect exists to refuse a hop that leaves TLS, and adding it without a count would have made the chain unbounded instead, so a server that redirects to itself forever would have been followed until the request timeout -- and the limit scanner would not have seen a thing, because the number it used to be was in someone else's package. | builtin/http.go |
httpRequestTimeout |
30s | duration | -- | httpRequestTimeout bounds one request an http_* builtin or lua_run_http makes, from dialling to the last byte of the body. | builtin/http.go |
httpTLSHandshakeTimeout |
10s | duration | -- | httpTLSHandshakeTimeout bounds the TLS handshake of one connection. | builtin/http.go |
luaRepeatResultMax |
8 MiB | bytes | -- | luaRepeatResultMax bounds how large a string string.rep may build inside the sandbox. | builtin/lua.go |
luaScriptTimeout |
5s | duration | -- | luaScriptTimeout bounds one lua_run_string / lua_run_file / lua_run_http call, from the first instruction of the chunk to its last. | builtin/lua.go |
maxArchiveListingBytes |
128 MiB | bytes | -- | maxArchiveListingBytes bounds the text a tar listing holds: every member's name, link target, user and group, added up. A collection of a million members averaging 128 bytes of it fits; a 44 KB archive of PAX records naming members a megabyte long does not. | builtin/archive.go |
maxBannerBytes |
4 KiB | bytes | -- | maxBannerBytes is the most a service's greeting may be. A banner is one line naming a product and a version -- "SSH-2.0-OpenSSH_9.6", "220 smtp.example ESMTP ready" -- and what a peer sends past four kibibytes of it is not a banner any more. The read is bounded because the peer decides when to stop talking: uncapped, a service that answers a connection with an endless stream would be recorded in full, into a VM variable that is re-encrypted on every store. A greeting that reaches the cap is refused rather than clipped, because the first four kibibytes of a longer stream reported as a whole banner is a wrong answer and nothing in the result could say so. | builtin/net.go |
maxBuiltinResultBytes |
32 MiB | bytes | -- | maxBuiltinResultBytes bounds a result whose size the script picks outright: a repeat count, a pad width, a number of random bytes. Uncapped, one mistyped count does not fail -- it leaves the process alive holding tens of gibibytes of the host's commit charge, printing nothing and surviving every ordinary kill, so the case it was opened for is never released. | builtin/result_limit.go |
maxCaseReason |
4 KiB | bytes | -- | maxCaseReason bounds a reason or a name written into a case record. It is written into a signed commit that is never compacted away, so it is a sentence and not a document. | builtin/case_lifecycle.go |
maxDecimalIntegerBytes |
4 KiB | bytes | -- | maxDecimalIntegerBytes bounds the integers rendered as decimal text. Turning a number into decimal costs more than linear time in its length -- a 512 KiB DER INTEGER took 550 ms, and four times that length twelve times as long (M26-DAT-029) -- and no integer a real document carries comes near it: a certificate serial is at most 20 bytes, an RSA-8192 modulus 1 KiB. A longer one is rendered in hexadecimal, which costs linear time and is as exact. | builtin/format_native.go |
maxEmailMultipartDepth |
16 | depth | -- | maxEmailMultipartDepth bounds how deeply multipart parts may nest inside one another. Mail as it is written nests three or four deep -- a multipart/mixed holding a multipart/related holding a multipart/alternative -- and every level is walked with its own boundary, so a message nested deeper than this is one built to make the walk recurse, and is refused rather than followed. | builtin/email_forensics.go |
maxHTTPBodyBytes |
32 MiB | bytes | -- | maxHTTPBodyBytes bounds the body an HTTP builtin hands back as one string: http_conn_read_request, http_conn_read_response, http_parse_request and http_parse_response, and also http_get, http_post and http_request, whose read had no bound of its own until M26-NET-021. A body past it is refused rather than cut. The peer at the other end decides how much it sends and is not trusted to be reasonable, and the body arrives as a VM variable, which is re-encrypted on every store. Refusing is what makes the answer honest: a clipped body returned as a whole one is a wrong result a script has no way to detect, which is what this cap used to produce (M26-NET-031). An intercepted message whose body may be larger is read with http_conn_read_request_head or http_conn_read_response_head plus net_conn_read, which leave the body on the connection and stream it in pieces; the three fetching builtins have no such streaming form, so a larger download is refused outright and the figure is what they are refused at. | builtin/mitm_http.go |
maxHTTPHeaderBytes |
1 MiB | bytes | -- | maxHTTPHeaderBytes bounds the request line and header block of one message. The body was capped and the head was not, so a peer could send a single header field of any length and have it read in full: an 8 MiB field grew the heap by 12 MiB and a 32 MiB field by 69 MiB, and both were accepted. A head is metadata about a body, and no real one is large. | builtin/mitm_http.go |
maxHTTPHeaderFields |
100 | count | -- | maxHTTPHeaderFields bounds how many header fields one HTTP message head may carry. The cost of a field is not its length: each one becomes an entry in an http.Header and then a pair in the hash a builtin hands back, which is held as a VM variable and re-encrypted on every store, so a field spelled in five bytes costs far more than five bytes and a bound counted in bytes does not see it. Measured with a 1 MiB head bound in place, 87,964 one-line fields fitted in 1,044,485 bytes on the wire and grew the heap by 33,246,576 -- 31.8 times what arrived (M26-NET-028). 100 is Apache httpd's LimitRequestFields default and Tomcat's maxHeaderCount default; net/http has no field count of its own to inherit, only byte bounds. | builtin/http_header_fields.go |
maxJSONDepth |
10,000 | depth | -- | maxJSONDepth bounds how deeply arrays and objects may nest in one document. It is the bound encoding/json's own decoder applied while these builtins used it, kept the same now that they read a document token by token, so nothing that parsed before is refused for its depth. | builtin/json.go |
maxJumplistStreamBytes |
64 MiB | bytes | -- | maxJumplistStreamBytes bounds one stream inside an automatic jump list. The stream is read into memory whole before anything looks at it, and the size comes from the compound file's own directory, which is a number in the file rather than evidence about it. A DestList of a few thousand destinations and a shell link are both far below this, so a stream above it is not one Windows wrote. | builtin/jumplist_builtins.go |
maxPcapPacketBytes |
128 MiB | bytes | -- | maxPcapPacketBytes is the ceiling on one pcap record, for the single case where the file's own size is no guide to it: pcapgo decompresses a gzipped capture transparently, and a compressed file's length bounds nothing inside it. | builtin/net.go |
maxPcapPackets |
1,000,000 | count | -- | maxPcapPackets is how many records net_capture_raw returns before it stops and marks the result truncated. Each record becomes a hash in a VM variable, so the cost is per packet rather than per byte, and a capture of a busy link holds far more packets than anyone reads at once. Past the cap the result says so, which is the difference between a short answer and a wrong one. | builtin/net.go |
maxPcapStreamBytes |
1,530,000,000 bytes | bytes | -- | maxPcapStreamBytes is the most a compressed capture may expand to while one of the three pcap builtins reads it. | builtin/net.go |
maxPlistDepth |
100 | depth | -- | maxPlistDepth bounds how deeply dictionaries and arrays may nest in one property list. A plist written by a tool nests a handful of levels deep -- a dict of dicts of arrays of strings -- and both parsers walk a level with a call, so a file nested deeper than this is one built to make the walk recurse. The bound is what the binary parser has always refused past; it is named here because the XML parser had no bound at all, and there was nothing for it to agree with (M26-ART-009). | builtin/plist_builtins.go |
maxRedactionLine |
4,096 | count | -- | maxRedactionLine bounds the walk back through a record's reclassifications. Each step is a reclassification an examiner recorded, so a line longer than this is not one anybody recorded by hand, and the walk refuses it rather than following it. | builtin/redaction_version.go |
maxRoleBundleViews |
256 | count | -- | maxRoleBundleViews bounds one bundle's view list. A bundle cannot usefully hold more views than a case would ever declare, and a longer list is one with repeats in it, which are refused on their own account anyway. | builtin/recipient_role.go |
maxSearchContext |
4 KiB | bytes | -- | maxSearchContext bounds the context at a page. A context is for recognising a hit; the passage around one is record_read's to return. | builtin/record_search.go |
maxSearchHits |
1,000 | count | -- | maxSearchHits bounds the hits one search hands back. It bounds the plaintext a result holds -- up to a context on each side of every hit -- and not the count, which covers every match in what was searched. | builtin/record_search.go |
maxSearchPattern |
4 KiB | bytes | -- | maxSearchPattern bounds the literal a search looks for. The matcher keeps a table as long as the pattern and every hit's context holds it, so an unbounded pattern is an unbounded allocation per hit; a page is room for any search term. | builtin/record_search.go |
maxZipLinkTargetBytes |
4 KiB | bytes | -- | maxZipLinkTargetBytes bounds how much of a zip symlink entry's body is read to learn where the link points. It is PATH_MAX on Linux, the longest target a link can be created with there. | builtin/archive.go |
sigmaKeywordMaxDepth |
256 | depth | -- | sigmaKeywordMaxDepth bounds how deep a keyword search walks an event. | builtin/sigma_engine.go |
sigmaWindashMaxVariants |
625 | count | -- | sigmaWindashMaxVariants bounds how many spellings one |windash value may expand into. |
builtin/sigma_engine.go |
`graphstore`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
WalkMaxEdges |
8,000,000 | count | -- | WalkMaxEdges bounds the edges one walk may read. It is four times the node bound because a walk reads every edge of every node it visits, and a node worth walking from has more than one. | graphstore/walk.go |
WalkMaxNodes |
2,000,000 | count | -- | WalkMaxNodes bounds the nodes one walk may visit. A walk that reaches two million has read most of a large store, which is a question to narrow -- to a set of ids, or a lower depth -- rather than one to answer. | graphstore/walk.go |
WalkMaxTime |
1m0s | duration | -- | WalkMaxTime bounds one walk's wall time. It is set well above the platform's clock granularity on purpose: graphene's own note is that on Windows the runtime reads the interrupt time, which advances at the timer tick -- 15.6 ms by default -- so a deadline in the microseconds is a deadline in name only; a probe with MaxTime 1ns completed a 201-node walk and reported no error at all. | graphstore/walk.go |
walkClockInterval |
16 | count | -- | walkClockInterval is how many charges pass between two reads of the clock when a budget sets MaxTime. It is graphene's own cadence, for graphene's reason: a clock read on every step of a walk that charges once per node and once per edge cost it about a fifth of its time, and sixteen steps is five or six nodes of overshoot. | graphstore/walk.go |
`lsp/internal/analyzer`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
maxFollowedNames |
8 | depth | -- | maxFollowedNames bounds how many names, slices and entries a rule follows from an argument back to where its value was made -- classifiedPlaintext to a read, filteredLedgerHandle to ledger_under_view. A chain longer than this is not worth the risk of following a binding somewhere it does not reach, and a rule that stops early stays quiet, which is the direction it errs in. | lsp/internal/analyzer/security_lint.go |
`lsp/internal/server`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
documentLinkStatBudget |
1,024 | count | -- | documentLinkStatBudget bounds how many distinct literals one documentLink request asks the filesystem about. | lsp/internal/server/link_path.go |
`parser`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
maxNestingDepth |
1,000 | depth | -- | maxNestingDepth bounds how deeply one construct may be nested inside another: parenthesised expressions, prefix operators, array and hash literals, calls, indexes, function literals and block bodies all count, because each one is a frame on the parser's stack. | parser/parser.go |
maxParseErrors |
100 | count | -- | maxParseErrors bounds how many errors one parse reports. | parser/parser.go |
`runner`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
maxArtifactFile |
1 GiB | bytes | -- | maxArtifactFile bounds the file a program is run from, read before anything knows what the file is. The largest artifact is a standalone executable -- the whole runtime, under 200 MiB even as a development build with debug information, plus its payload -- so a real program is far below it, and a disk image or a memory dump named by mistake is refused before it is read into memory rather than after. | runner/runner.go |
maxBytecode |
256 MiB | bytes | -- | maxBytecode bounds what an artifact's bytecode may inflate to. A zstd frame declares its own content size, so a payload of a few kilobytes can ask the decoder for gigabytes; the bound is checked while inflating, before gob sees a byte. The largest program in examples/, 25 KB of source, compiles to a 50 KB artifact. | runner/runner.go |
processProtectionTerminateConfidence |
80 | score | -- | processProtectionTerminateConfidence is the confidence from which a process-protection signal stops a secure-mode run. With the probes' scores as they are (security/antitamper_constants.go), a redirected import (90), a suspicious module (85), writable and executable API pages (92) or hooks on two or more APIs (90) stop the run; a hook on one API (75) or an injector process (70) does not. | runner/runner.go |
`security`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
DefaultArgon2Memory |
64 MiB | kibibytes | -- | DefaultArgon2Memory is the Argon2id memory cost of an artifact's password key, in the kibibytes Argon2 counts in: 64 MiB. | security/kdf.go |
DefaultArgon2Threads |
4 | count | -- | DefaultArgon2Threads is the Argon2id lane count of an artifact's password key: four, as both of RFC 9106's recommended parameter sets use. | security/kdf.go |
DefaultArgon2Time |
1 | iterations | -- | DefaultArgon2Time is the Argon2id pass count an artifact's password key is derived with. The generator writes the cost into the artifact beside the salt and the runner derives with what the artifact says, so the default can change without stranding an artifact already written. One pass over DefaultArgon2Memory meets OWASP's Argon2id minimum for a single pass, 46 MiB. | security/kdf.go |
DefaultSegmentSize |
64 KiB | bytes | -- | DefaultSegmentSize is 64 KiB: small enough that a disclosure is granular, large enough that the per-segment tag and key derivation are noise. | security/record_file.go |
DefaultTamperDelayMs |
250ms | milliseconds | -- | DefaultTamperDelayMs is how long the delay response pauses a run that tripped a detector before letting it continue. No mode selects that response -- secure mode terminates, --compat and --dev warn -- so no run waits on it today; it is the value the response would use if a mode did. | security/response_policy.go |
MaxArgon2Memory |
256 MiB | kibibytes | -- | MaxArgon2Memory bounds the memory an artifact's header may ask for, at the same costliest derivation MaxArgon2Time stops at: 256 MiB. | security/kdf.go |
MaxArgon2Threads |
4 | count | -- | MaxArgon2Threads bounds the lanes an artifact's header may ask for, at the four every derivation in the tree uses. | security/kdf.go |
MaxArgon2Time |
3 | iterations | -- | MaxArgon2Time bounds the passes an artifact's header may ask for. The runner derives the key before it has anything to authenticate the header with, so this is a cost a crafted header could name. It stops at the costliest derivation in the tree -- caseKeyProfiles' and grantFileProfiles' three passes over 256 MiB in four lanes, which TestCaseKeyProfileIsInBand holds inside these bounds. | security/kdf.go |
MaxClassLabel |
64 bytes | bytes | -- | MaxClassLabel is the longest class label a tag will be computed over. A label ends up in a report, a CSV and possibly a court exhibit. | security/record_crypto.go |
MaxRecordFooter |
1 MiB | bytes | -- | MaxRecordFooter bounds the footer, which is read and parsed before a signature has been checked. It is not a limit an honest record meets. | security/record_file.go |
MaxRecordHeader |
8 MiB | bytes | -- | MaxRecordHeader bounds the header, which is read and parsed before a signature has been checked. It is not a limit an honest record meets. | security/record_file.go |
MaxRecordSegments |
1,048,576 | count | -- | MaxRecordSegments bounds the DERIVED segment table, which is the number MaxRecordSpans does not bound and the one a hostile header controls. | security/record_file.go |
MaxRecordSpans |
4,096 | count | -- | MaxRecordSpans bounds the classification ranges one record may carry. A span list is read by a person deciding whether a disclosure is fair, and past a few thousand rows nobody is reading it. | security/record_file.go |
MaxSegmentPlaintext |
1 MiB | bytes | -- | MaxSegmentPlaintext keeps every call far below the size at which chacha20poly1305 panics instead of returning an error. A segment is a unit of disclosure, not a unit of storage; a record has as many as it needs. | security/record_crypto.go |
MinArgon2Memory |
64 MiB | kibibytes | -- | MinArgon2Memory is the least memory an artifact's header may ask for: the default this build writes, so a header edited down to a cheap derivation is refused rather than honoured. | security/kdf.go |
SandboxDetectedThreshold |
70 | score | -- | SandboxDetectedThreshold is the confidence from which a run counts as sandboxed, by the run's own checks and by the status builtins alike. A detector adds up its indicators' confidences per sandbox type; on Linux, for one, the specific indicators -- a Docker or WSL marker, a VM vendor in the CPU or the firmware -- reach it alone, and the generic ones, such as the CPU's hypervisor flag, do not. | security/sandbox.go |
SleepDriftNaps |
3 | iterations | -- | SleepDriftNaps is how many sleepDriftNap naps the sleep_drift probe times. | security/antitamper_constants.go |
SleepDriftThresholdMs |
10ms | milliseconds | -- | SleepDriftThresholdMs is how far the naps' total may run past what they asked for before the probe reports it. Three 1 ms naps take four to six milliseconds on an idle Windows machine; ten more than asked for is a thread that was stopped, not one that was scheduled late. | security/antitamper_constants.go |
TimingLoopIterations |
200,000 | iterations | -- | TimingLoopIterations is the length of the timing probe's loop: enough work to be timed, little enough to cost nothing. | security/antitamper_constants.go |
TimingSuspiciousThresholdUs |
200ms | microseconds | -- | TimingSuspiciousThresholdUs is how long the loop may take before the timing probe reports it. The loop runs in well under a millisecond on an unhindered machine -- the Windows clock reads it as 0 or 1 ms -- so two hundred is a thread stopped part way through, single-stepped or suspended, and not a slow one. | security/antitamper_constants.go |
defaultCommandExecTimeout |
3s | milliseconds | -- | defaultCommandExecTimeout is how long exec_string and cmd_run let a command run before the shell is killed and the result says timed_out: long enough for a shell to start and answer a short query of the host, short enough that a hung command does not hang the script. | security/command_exec.go |
defaultCommandMaxOutput |
8 KiB | bytes | -- | defaultCommandMaxOutput is how much of each of a command's output streams exec_string and cmd_run hand back; what is past it is cut and marked as truncated. A result is for reading an answer, not for capturing a transcript. | security/command_exec.go |
defaultCommandWaitDelay |
500ms | milliseconds | -- | defaultCommandWaitDelay is how much longer than the timeout above one call may last. The clock starts when the deadline passes or when the command's own process exits, whichever comes first, and what it bounds is the wait for everything else the command started: a grandchild holding the output pipe open used to keep the call alive for as long as it liked, whatever the timeout said -- cmd /C ping -n 10 127.0.0.1 took 9.14 seconds against a 3-second timeout and then reported that it had timed out (M26-TMP-006). Half a second is long enough for a killed process tree to die and let go of its handles on a loaded host, and short enough that the worst case of exec_string stays under four seconds. |
security/command_exec.go |
defaultRemoteScanCritical |
85 | score | -- | defaultRemoteScanCritical is the verdict score from which the scan records a process as critical and, in enforce mode, stops the run; its "critical" band starts here. Like defaultRemoteScanHighRisk, only tests ever reach it. | security/processscan_config.go |
defaultRemoteScanHighRisk |
70 | score | -- | defaultRemoteScanHighRisk is the verdict score from which the remote process scan records a process as suspicious, and where its "high" risk band starts. The scan is off in every shipped binary and its Windows scanner returns no verdicts, so only tests, which supply their own verdicts, ever reach these scores. | security/processscan_config.go |
outputDebugTimingThresholdTicks |
10ms | milliseconds | -- | outputDebugTimingThresholdTicks is how many milliseconds, as GetTickCount counts them, an OutputDebugString call may take before it counts as a debugger's. GetTickCount moves a timer tick at a time, so this fires when the call spans a tick: likely for a call a debugger stops to receive, rare for one nobody receives. | security/antidebug_windows.go (windows) |
remoteScanMediumScore |
40 | score | -- | remoteScanMediumScore is where the "medium" risk band starts; below it a verdict is "low". It labels a verdict and decides nothing. | security/processscan_config.go |
sleepDriftNap |
1ms | duration | -- | sleepDriftNap is one of the sleep_drift probe's naps: the shortest sleep worth asking the scheduler for. | security/antitamper_detectors.go |
weakSignalTriggerThreshold |
2 | count | -- | weakSignalTriggerThreshold is how many of the weak checks must fire together before they count as a debugger. There are two -- the OutputDebugString timing and a debugger's DLL in the process -- and either alone is common on a developer's machine. | security/antidebug_windows.go (windows) |
`vm`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
maxCallDepth |
10,000 | depth | -- | maxCallDepth is how many calls may be on the stack at once. The next one past it is refused with an error naming the number, which is a diagnostic the author can act on; what happened before was not. | vm/vm.go |
The tools around Mutant#
These bound the programs that build, test and document Mutant -- the example sweeper, the generators, the test helpers and the limit guard itself -- and never a run of it.
`policy/limitscan`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
maxShownExpression |
80 bytes | bytes | -- | maxShownExpression bounds how much of an expression a finding quotes, so a failure message stays one line per finding. | policy/limitscan/limitscan.go |
`testkit`#
| Limit | Value | Unit | Flag | Why | File |
|---|---|---|---|---|---|
GoroutineSettleTimeout |
5s | duration | -- | GoroutineSettleTimeout is how long CheckGoroutines waits, after a test ends, for the goroutines it started to finish. Long enough for a closed listener's accept loop or a cancelled context's workers to notice; short enough that a genuine leak fails in seconds rather than at the package timeout. | testkit/goroutines.go |
goroutinePollInterval |
10ms | duration | -- | goroutinePollInterval is how often the count is re-read while settling. | testkit/goroutines.go |
goroutineStackBuffer |
64 KiB | bytes | -- | goroutineStackBuffer is the initial buffer for a full stack dump; it doubles until the dump fits. | testkit/goroutines.go |