pruntime

package
v0.4.171 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2024 License: ISC Imports: 11 Imported by: 1

Documentation

Overview

Package pruntime provides an interface to the Go standard library’s runtime package using only serializable simple types

Stack traces and code locations have several formats:

codeLocation := pruntime.NewCodeLocation(0)
codeLocation.Base() // package and type
  → mypackage.(*MyType).MyFunc
codeLocation.PackFunc() // very brief
  → mypackage.MyFunc
codeLocation.Name(): // function name only
  → MyFunc
codeLocation.Short() // line, no package path
  → mypackage.(*MyType).MyFunc-myfile.go:19
codeLocation.Long() // uniquely identifiable
  → codeberg.org/haraldrudell/mypackage.(*MyType).MyFunc-myfile.go:19
codeLocation.Full() // everything
  → codeberg.org/haraldrudell/mypackage.(*MyType).MyFunc-/fs/mypackage/myfile.go:19
codeLocation.String() // two lines
  → "codeberg.org/haraldrudell/mypackage.(*MyType).MyFunc\n  /fs/mypackage/myfile.go:19"

Stack can determine where a goroutine was created and whether this is the main thread

pruntime.GoRoutineID()  → 1
pruntime.NewStack(0).Creator.Short()  → main.main-pruntime.go:30
fmt.Println(pruntime.NewStack(0).IsMainThread)  → true
pruntime.NewStack(0).Frames[0].Args  → (0x104c12c60?)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendLocation added in v0.4.114

func AppendLocation(s string, location *CodeLocation) string

AppendLocation inserts CodeLocation.Short at the end of s, prior to a possible newline

func DebugStack added in v0.4.12

func DebugStack(skipFrames int) (stack string)

DebugStack returns a string stack trace intended to be printed or when a full printable trace is desired

  • top returned stack frame is caller of pruntime.DebugStack
  • skipFrames allows for removing additional frames.
  • differences from debug.Stack:
  • tabs are replaced with two spaces
  • Stack frames other than the callers of pruntime.DebugStack are removed

func FirstStackLine added in v0.4.99

func FirstStackLine() (firstStackLine []byte)

FirstStackLine efficiently obtains the first line of a runtime.Stack

  • "goroutine 34 [running]:\n…"
  • interning the first line as a string will cost about 25 bytes

func Invocation

func Invocation(stackFramesToSkip int) (stackTrace string)

Invocation returns an invocation stack trace for debug printing, empty string on troubles. The result is similar to the output from debug.Stack, but has some stack frames removed. tabs are replaced by two spaces. stackFramesToSkip 0 means first frame will be the caller of Invocation "goroutine 1 [running]:\ngithub.com/haraldrudell/parl/mains.(*Executable).AddErr(0x1809300, 0x158b620, 0xc000183800, 0x1) mains.(*Executable).AddErr-executable.go:302…"

func IsCloseOfClosedChannel added in v0.4.103

func IsCloseOfClosedChannel(err error) (is bool)

IsCloseOfClosedChannel returns true if err’s error chain contains the runtime error “close of closed channel”

func IsRuntimeError

func IsRuntimeError(err error) (err1 runtime.Error)

IsRuntimeError determines if err’s error chain contains a runtime.Error

  • err1 is then a non-nil error value
  • runtime.Error is an interface describing the unexported runtime.plainError type

func IsSendOnClosedChannel

func IsSendOnClosedChannel(err error) (is bool)

IsSendOnClosedChannel returns true if err’s error chain contains the runtime error “send on closed channel”

  • runtime.plainError is an unexported named type of underlying type string
  • each error occurrence has a unique runtime.plainError value
  • runtime.plainError type have empty method RuntimeError()
  • the runtime.Error interface has the RuntimeError method
  • the Error method of runtime.Error returns the string value

func StackTrace added in v0.4.106

func StackTrace() (stackTrace []byte)

StackTrace returns runtime.Stack after allocating sufficient buffer

  • if the entire stackTrace is converted to string and split: those substrings will be interned part of the larger stackTrace string causing memory leak, ie. If only a single character is kept, the entire block is kept. This leads to megabytes of memory leaks
  • StackTrace returns a byte slice for convert smaller indiviual parts to string
  • the stack trace contains spaces, newlines and tab characters for formatting
  • the first line is status line
  • each frame is then two lines:
  • — a function line with argument values
  • — a filename line beginning with a tab character and a hexadecimal in-line byte offset
  • the first line-pair is for the StackTrace function itself
  • if the executing thread is a goroutine:
  • — the final two lines is “created by,” ie. the location of the go statement and what thread started the goroutine
  • — the two preceding lines is the goroutine function
  • the stack trace has a terminating newline

Types

type CacheMechanic added in v0.4.131

type CacheMechanic struct {
	// contains filtered or unexported fields
}

CacheMechanic ensures that an init function is executed exactly once

  • sync.Once using a known number of stack frames
  • initialization-free

func (*CacheMechanic) EnsureInit added in v0.4.131

func (c *CacheMechanic) EnsureInit(initFunc func())

EnsureInit ensures data is loaded exactly once

  • initFunc loads data
  • invocations after first EnsureInit return are atomic performance
  • first invocation is locked performance
  • subsequent invocations prior to first EnsureInit return are held waiting
  • upon return, it is guaranteed that init has completed
  • order of thread-returns is not guaranteed

type CachedLocation added in v0.4.87

type CachedLocation struct {
	// contains filtered or unexported fields
}

CachedLocation caches the code location and performantly provides it in string formats. Thread-safe

  • one top-level CachedLocation variable is required for each code location
  • code line provided is the location of first getter method
  • caching saves 1,003 ns, ie. 0.85 parallel mutex Lock/Unlock
  • cannot use sync.Once.Do because number of frames it consumes is unknown
  • initialization-free, thread-safe

usage:

var mycl pruntime.CachedLocation
func f() {
  println(mycl.PackFunc())

func (*CachedLocation) FuncIdentifier added in v0.4.88

func (c *CachedLocation) FuncIdentifier() (funcIdentifier string)

"myFunc" Thread-safe

func (*CachedLocation) FuncName added in v0.4.87

func (c *CachedLocation) FuncName() (location string)

"github.com/haraldrudell/parl/mains.(*Executable).AddErr" Thread-safe

  • FuncName is the value compared to by [parl.SetRegexp]

func (*CachedLocation) PackFunc added in v0.4.87

func (c *CachedLocation) PackFunc() (packFunc string)

"mains.AddErr" Thread-safe

  • similar to [perrors.NewPF] or [perrors.ErrorfPF]

func (*CachedLocation) Short added in v0.4.87

func (c *CachedLocation) Short() (location string)

"mains.(*Executable).AddErr-executable.go:25" Thread-safe

  • similar to [perrors.Short] location

type CodeLocation

type CodeLocation struct {
	// File is the absolute path to the go source file
	//
	//  /opt/foxyboy/sw/privates/parl/mains/executable.go
	File string
	// Line is the line number in the source file, eg. 35
	Line int
	// FuncName is the fully qualified Go package path,
	// a possible value or pointer receiver struct name,
	// and the function name
	//
	//  github.com/haraldrudell/parl/mains.(*Executable).AddErr
	FuncName string
}

CodeLocation represents an executing code location, ie. a code line in source code

  • CodeLocation is similar to the location in runtime.Frame, but contains only basic types string and int

func NewCodeLocation

func NewCodeLocation(stackFramesToSkip int) (cl *CodeLocation)

NewCodeLocation gets data for a single stack frame

  • for stackFramesToSkip 0, NewCodeLocation returns data for its immediate caller

func (*CodeLocation) Base

func (cl *CodeLocation) Base() (baseName string)

Base returns base package name, an optional type name and the function name:

mains.(*Executable).AddErr

func (*CodeLocation) Dump added in v0.4.92

func (cl *CodeLocation) Dump() (s string)

Dump outputs all values quoted for debug purposes

File: "/opt/homebrew/Cellar/go/1.20.4/libexec/src/testing/testing.go"
Line: 1576 FuncName: "testing.tRunner"

func (*CodeLocation) Full

func (cl *CodeLocation) Full() (funcName string)

Full returns all available information on one line the function name, base filename and line number:

mains.(*Executable).AddErr-executable.go:25

func (*CodeLocation) FuncIdentifier added in v0.4.88

func (cl *CodeLocation) FuncIdentifier() (funcIdentifier string)

FuncIdentifier return the function name identifier “AddErr”

  • no spaces

func (*CodeLocation) FuncLine added in v0.4.29

func (cl *CodeLocation) FuncLine() (funcLine string)

"github.com/haraldrudell/parl/mains.(*Executable).AddErr:43"

func (*CodeLocation) IsSet added in v0.4.25

func (cl *CodeLocation) IsSet() (isSet bool)

IsSet returns true if this CodeLocation has a value, ie. is not zero-value

func (*CodeLocation) Long

func (cl *CodeLocation) Long() (funcName string)

Long returns full package path, an optional type name and the function name, base filename and line number:

mains.(*Executable).AddErr-executable.go:25

func (*CodeLocation) Name

func (cl *CodeLocation) Name() (funcName string)

FuncName returns function name, characters no space:

AddErr

func (*CodeLocation) PackFunc

func (cl *CodeLocation) PackFunc() (packageDotFunction string)

PackFunc return base package name and function “mains.AddErr”

func (*CodeLocation) Package

func (cl *CodeLocation) Package() (packageName string)

Package return base package name, a single word of characters with no space:

mains

func (*CodeLocation) Short

func (cl *CodeLocation) Short() (funcName string)

Short returns base package name, an optional type name and the function name, base filename and line number:

mains.(*Executable).AddErr-executable.go:25

func (CodeLocation) String

func (cl CodeLocation) String() string

String returns a two-line string representation suitable for a multi-line stack trace. Typical output:

github.com/haraldrudell/parl/error116.(*TypeName).FuncName␤
␠␠/opt/sw/privates/parl/error116/codelocation_test.go:20

type Frame added in v0.4.162

type Frame interface {
	// the code location for this frame, never nil
	Loc() (location *CodeLocation)
	// function argument values like “(1, 0x14000113040)”
	//	- values of basic types like int are displayed
	//	- most types appear as a pointer value “0x…”
	Args() (args string)
	// prints the Frame suitable to be part of a stack trace
	//   - fully qualified package name with function or type and method
	//     and argument values
	//   - absolute path to source file and line number
	//
	// output:
	//
	//	github.com/haraldrudell/parl/pdebug.TestFrame(0x1400014a340)␤
	//	␠␠frame_test.go:15
	String() (s string)
}

Frame represents an executing code location, ie. a code line in source code

  • parl.Frame is similar to runtime.Frame returned by runtime.CallersFrames but has only basic types, ie. it can be printed, stored and transferred
  • a lis of Frame is returned by [Stack.Frames]

type FrameR added in v0.4.162

type FrameR struct {
	CodeLocation
	// contains filtered or unexported fields
}

Frame represents an executing code location, ie. a code line in source code

  • parl.Frame is similar to runtime.Frame returned by runtime.CallersFrames but has only basic types, ie. can be stored or transferred
  • [pdebug.Frame] implements [parl.Frame]
  • Frame is a value container only created by [pdebug.NewStack]. Frame extends pruntime.CodeLocation with argument values

func (*FrameR) Args added in v0.4.162

func (f *FrameR) Args() (args string)

function argument values like "(1, 0x14000113040)"

  • values of basic types like int are displayed
  • most types appear as a pointer value “0x…”

func (*FrameR) Loc added in v0.4.162

func (f *FrameR) Loc() (location *CodeLocation)

the code location for this frame, never nil

func (*FrameR) String added in v0.4.162

func (f *FrameR) String() (s string)

prints the Frame suitable to be part of a stack trace

  • fully qualified package name with function or type and method and argument values
  • absolute path to source file and line number

output:

github.com/haraldrudell/parl/pdebug.TestFrame(0x1400014a340)␤
␠␠frame_test.go:15

type Stack added in v0.4.162

type Stack interface {
	// true if the thread is the main thread
	//	- false for a launched goroutine
	IsMain() (isMain bool)
	// A list of code locations for this thread
	//	- index [0] is the most recent code location, typically the invoker requesting the stack trace
	//	- includes invocation argument values
	Frames() (frames []Frame)
	// the goroutine function used to launch this thread
	//	- if IsMain is true, zero-value. Check using GoFunction().IsSet()
	//	- never nil
	GoFunction() (goFunction *CodeLocation)
	// Shorts lists short code locations for all stack frames, most recent first:
	// Shorts("prepend") →
	//  prepend Thread ID: 1
	//  prepend main.someFunction()-pruntime.go:84
	//  prepend main.main()-pruntime.go:52
	Shorts(prepend string) (s string)
	// String is a multi-line stack trace, most recent code location first:
	//  ID: 18 IsMain: false status: running␤
	//  main.someFunction({0x100dd2616, 0x19})␤
	//  ␠␠pruntime.go:64␤
	//  cre: main.main-pruntime.go:53␤
	fmt.Stringer
}

Stack is implemented by:

func NewStack added in v0.4.162

func NewStack(skipFrames int) (stack Stack)

NewStack populates a Stack object with the current thread and its stack using debug.Stack

type StackR added in v0.4.162

type StackR struct {
	// ThreadID is a unqique ID associated with this thread.
	// typically numeric string “1”…
	//	- [constraints.Ordered] [fmt.Stringer] [ThreadID.IsValid]
	ThreadID uint64
	// Status is typically word “running”
	Status string

	// Creator is the code location of the go statement launching
	// this thread
	//	- FuncName is "main.main()" for main thread
	Creator CodeLocation
	// possible ID of creating goroutine
	CreatorID uint64
	// creator goroutine reference “in goroutine 1”
	GoroutineRef string
	// contains filtered or unexported fields
}

Stackr is a parl-free [pdebug.Stack]

  • Go stack traces are created by runtime.Stack and is a byte slice
  • debug.Stack repeatedly calls runtime.Stack with an increased buffer size that is eventually returned
  • debug.PrintStack writes the byte stream to os.Stderr
  • interning large strings is a temporary memory leak. Converting the entire byte-slice stack-trace to string retains the memory for as long as there is a reference to any one character. This leads to megabytes of memory leaks

func (*StackR) Dump added in v0.4.162

func (s *StackR) Dump() (s2 string)

func (*StackR) Frames added in v0.4.162

func (s *StackR) Frames() (frames []Frame)

A list of code locations for this thread

  • index [0] is the most recent code location, typically the invoker requesting the stack trace
  • includes invocation argument values

func (*StackR) GoFunction added in v0.4.162

func (s *StackR) GoFunction() (goFunction *CodeLocation)

the goroutine function used to launch this thread

  • if IsMain is true, zero-value. Check using GoFunction().IsSet()
  • never nil

func (*StackR) IsMain added in v0.4.162

func (s *StackR) IsMain() (isMainThread bool)

true if the thread is the main thread

  • false for a launched goroutine

func (*StackR) Shorts added in v0.4.162

func (s *StackR) Shorts(prepend string) (shorts string)

Shorts lists short code locations for all stack frames, most recent first: Shorts("prepend") →

prepend Thread ID: 1
prepend main.someFunction()-pruntime.go:84
prepend main.main()-pruntime.go:52

func (*StackR) String added in v0.4.162

func (s *StackR) String() (s2 string)

String is a multi-line stack trace, most recent code location first:

ID: 18 IsMain: false status: running␤
main.someFunction({0x100dd2616, 0x19})␤
␠␠pruntime.go:64␤
cre: main.main-pruntime.go:53␤

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL