• Stars
    star
    162
  • Rank 232,284 (Top 5 %)
  • Language
    Go
  • License
    MIT License
  • Created almost 7 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

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.

More Repositories

1

go-sqlbuilder

A flexible and powerful SQL string builder library plus a zero-config ORM.
Go
1,445
star
2

xstrings

Implements string functions widely used in other languages but absent in Go.
Go
1,398
star
3

facebook

A Facebook Graph API SDK For Go.
Go
1,330
star
4

skiplist

Fast and easy-to-use skip list for Go.
Go
375
star
5

go-clone

Clone any Go data structure deeply and thoroughly.
Go
302
star
6

goroutine

[DEPRECATED] Expose goroutine id to wild world. Alternative approach is https://github.com/huandu/go-tls
Go
111
star
7

go-assert

Magic assert macros for Go.
Go
27
star
8

gin

gin - a simple & efficient HTML5 game engine
JavaScript
25
star
9

node-ascii85

Ascii85 (Base85) encoding/decoding module for node.js.
JavaScript
18
star
10

ObjCMixin

A ruby-like mixin in Object-C.
Objective-C
10
star
11

gin-samples

Samples using the gin
JavaScript
9
star
12

spritemapper

A Java program which creates sprite maps (or sprite sheets) from a set of input images.
Java
9
star
13

nocycle.js

Detect cycle `require` in node.js.
JavaScript
9
star
14

go-magicstring

Attach arbitrary data to a Go string
Go
7
star
15

handyhttpd

A handy http server to enable public http access on any folder within a few seconds.
Go
6
star
16

yuki

A flexible and efficient mysql client written in C
C
5
star
17

bashtools

Several bash scripts to make life easier
Shell
3
star
18

go-singleton

Generic singleton for Go.
Go
2
star
19

heybox-url

Calculate Heybox url hash.
JavaScript
2
star
20

node-facter

A wrapper for puppet `facter` tool
JavaScript
2
star
21

express-handler

Provide a per-request `this` object for express router handlers.
JavaScript
1
star
22

design-doc-chs

1
star