GithubHelp home page GithubHelp logo

huandu / go-tls Goto Github PK

View Code? Open in Web Editor NEW
162.0 10.0 16.0 36 KB

A bit safer approach to implement Thread Local Storage (TLS) for Go 1.7+.

License: MIT License

Go 79.10% Assembly 18.39% C 2.51%
golang tls hack goroutine experimental thread-local-storage

go-tls's Introduction

go-tls: TLS for any goroutine

CircleCI GoDoc

⚠️ This package doesn't support Go1.17.* due to Go runtime changes. Don't use this package until #10 is resolved.

WARNING: It's not recommended to use this package in any production environment. It may crash you at any time. Use context instead when possible.

Package tls provides TLS for any goroutine by hijacking runtime.goexit on stack. Comparing with other similar packages, this package avoids any potential resource leak in TLS.

Install

Use go get to install this package.

    go get github.com/huandu/go-tls

Use TLS

Set arbitrary data and get it later.

k := "my key"
v := 1234
tls.Set(k, tls.MakeData(v))

// Get data by k.
d, ok := tls.Get(k)
assert(ok)
assert(d.Value().(int) == v)

// Get a unique ID for current goroutine.
// It's guaranteed to be unique.
id := tls.ID()

// Delete data by k.
tls.Del(k)

// Reset TLS so that all keys are removed and all data is closed if necessary.
// It doesn't remove any AtExit handler.
tls.Reset()

// Completely unload TLS and discard all data and AtExit handlers.
// If TLS method is called after Unload, a new TLS stub will be created.
// The ID() will return a different value.
tls.Unload()

If the data implements io.Closer, it will be called automatically when Reset is called or goroutine exits. It's not allowed to use any TLS methods in the Close method of TLS data. It will cause permanent memory leak.

Execute code when goroutine exits

AtExit pushes a function to a slice of at-exit handlers and executes them when goroutine is exiting in FILO order. All TLS data is still available when calling at-exit handlers.

AtExit doesn't work on main goroutine as it doesn't exit at all.

tls.AtExit(func() {
    // Do something when goroutine is exiting...
})

Limitations

Several limitations so far.

  • Works with Go 1.7 or newer.
  • AtExit doesn't work on main goroutine, as this goroutine always exits with os.Exit(0) instead of calling goexit. See main() in src/runtime/proc.go.

How it works

It's quite a long story I don't have time to write everything down right now.

TL; DR. Package tls uses goroutine's g struct pointer to identify a goroutine and hacks runtime.goexit to do house clean work when goroutine exits.

This approach is relatively safe, because all technics are based on runtime types which doesn't change since Go1.0.

Following runtime types are used.

  • The g.stack: It's the first field of g. It stores stack memory range of a g.
  • Function symbol table: When Go runtime allocates more stack, it validates all return addresses on stack. If I change runtime.goexit to another function pc, runtime will complain it as it's not a valid top of stack function (checked by runtime.topofstack). As a workaround, I hacks function symbol table to set _func.pcsp of the hacked goexit to 0 to skip checks.

Similar packages

  • github.com/jtolds/gls: Goroutine local storage on current goroutine's stack. We must start goroutines with Go func explicitly before using any context methods.
  • github.com/v2pro/plz/gls: Use goid as a unique key for any goroutine and store contextual information.

License

This package is licensed under MIT license. See LICENSE for details.

go-tls's People

Contributors

huandu avatar okhowang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-tls's Issues

Question about using g struct pointer to identify a goroutine

I am looking for a lib to identify a goroutine, and I don't like to use goroutine id.

This lib is promising.

And I have a question: goroutine may migrate between system threads, using g struct pointer to identify a goroutine may be not reliable. What do you think about this situation?

tls.Unload error in goroutine exit

code as fallow:

func CreateGls() {
	zaplog.LoggerSugar.Debugf("GLS create goid:%d", GoID())
	TLS.AtExit(func() {
		zaplog.LoggerSugar.Debugf("GLS delete goid:%d", GoID())
		TLS.Unload()
	})
}

testcase:

func TestAutoReleaseWhenGoExit(t *testing.T) {
	go func() {
		CreateGls()
		time.Sleep(10*time.Second)
	}()

	zaplog.LoggerSugar.Debugf("main goroutine goid:%d", GoID())
	time.Sleep(20*time.Second)
	zaplog.LoggerSugar.Debugf("main goroutine exit")
}

error occurs like this:

=== RUN TestAutoReleaseWhenGoExit
2020-10-20T17:39:25.252+0800 DEBUG gls/gls_test.go:15 main goroutine goid:1
2020-10-20T17:39:25.252+0800 DEBUG gls/gls.go:17 GLS create goid:2
2020-10-20T17:39:35.255+0800 DEBUG gls/gls.go:19 GLS delete goid:2
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x12baa6a]

goroutine 6 [running]:
server/internal/common/gls/internal/tls.resetAtExit()
/Users/yc/workspace/goproject/uuu/antia-server/internal/common/gls/internal/tls/tls.go:175 +0x17a
server/internal/common/gls/internal/tls.hackedGoexit1()
/Users/yc/workspace/goproject/uuu/antia-server/internal/common/gls/internal/tls/goexit.go:72 +0x22
created by server/internal/common/gls.TestAutoReleaseWhenGoExit
/Users/yc/workspace/goproject/uuu/antia-server/internal/common/gls/gls_test.go:10 +0x39

Process finished with exit code 1

启动不起来了,Apple M1 Max

panic: tls: fail to call mprotect(addr=0x10618d910, size=40, prot=0x2) with error invalid argument

goroutine 1 [running]:
github.com/huandu/go-tls.mprotect(0x10618d910, 0x28, 0x2)
/Users/xxx/work/go/pkg/mod/github.com/huandu/[email protected]/syscall_unix.go:34 +0x250
github.com/huandu/go-tls.init.1()
/Users/xxx/work/go/pkg/mod/github.com/huandu/[email protected]/goexit.go:63 +0xd8
Exiting.

Debugger finished with the exit code 0

full link ID based on TLS ?

In order to achieve full link ID tracking, based on TLS in go, in order to avoid function calls need to pass the context param .In the same coroutine, it is OK to get the link ID according to the coroutine ID, but how can one coroutine start another coroutine without obvious the passing link ID?

broken @go1.17

go 1.17 it is relased.

And this repo will broken at the unit test.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.