Commit 9b44fc23 authored by Kirill Smelkov's avatar Kirill Smelkov

X Unfortunately it crashes in GC even with weak.Ref reworked to be one word instead of two

    ---- 8< ----
    (z-dev) kirr@deca:~/src/wendelin/wendelin.core/wcfs$ time ./gogccrash 2>&1

    done, crashes:
    BUG/2/core

    Завершено

    real    28m54,016s
    user    30m27,968s
    sys     7m35,028s

    (z-dev) kirr@deca:~/src/wendelin/wendelin.core/wcfs$ cat BUG/2/log

    ...

    runtime: full=0xc0001f10000005 next=205 jobs=204 nDataRoots=1 nBSSRoots=1 nSpanRoots=16 nStackRoots=184
    panic: non-empty mark queue after concurrent mark
    fatal error: panic on system stack

    ...
    ---- 8< ----
parent 451d1e3f
This diff is collapsed.
This diff is collapsed.
module lab.nexedi.com/nexedi/wendelin.core/wcfs
go 1.14
go 1.18
require (
github.com/kisielk/og-rek v1.0.1-0.20180928202415-8b25c4cefd6c
lab.nexedi.com/kirr/go123 v0.0.0-20200916121347-316617668e12
lab.nexedi.com/kirr/neo/go v0.0.0-20201012044742-28494187df87
)
// indirects
require (
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537
github.com/DataDog/czlib v0.0.0-20160811164712-4bc9a24e37f2
github.com/fsnotify/fsnotify v1.4.10-0.20200417215612-7f4cf4dd2b52
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/philhofer/fwd v1.0.0
github.com/pkg/errors v0.9.1
github.com/someonegg/gocontainer v1.0.0
github.com/shamaton/msgpack v1.1.1
github.com/tinylib/msgp v1.1.3-0.20200327023543-e88e92c0ccca
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
)
......@@ -117,7 +117,7 @@ type LiveCache struct {
//
// NOTE2 finalizers don't run on when they are attached to an object in cycle.
// Hopefully we don't have cycles with BTree/Bucket.
objtab map[Oid]*weak.Ref // oid -> weak.Ref(IPersistent)
objtab map[Oid]*weak.Ref[Persistent] // oid -> weak.Ref(IPersistent)
// hooks for application to influence live caching decisions.
control LiveCacheControl
......@@ -184,7 +184,7 @@ func newConnection(db *DB, at Tid) *Connection {
at: at,
cache: LiveCache{
pinned: make(map[Oid]IPersistent),
objtab: make(map[Oid]*weak.Ref),
objtab: make(map[Oid]*weak.Ref[Persistent]),
},
}
}
......@@ -231,7 +231,7 @@ func (cache *LiveCache) Get(oid Oid) IPersistent {
wobj := cache.objtab[oid]
if wobj != nil {
if xobj := wobj.Get(); xobj != nil {
obj = xobj.(IPersistent)
obj = xobj.instance
}
}
......@@ -252,7 +252,7 @@ func (cache *LiveCache) setNew(oid Oid, obj IPersistent) {
cache.pinned[oid] = obj
// XXX assert .objtab[oid] == nil ?
} else {
cache.objtab[oid] = weak.NewRef(obj)
cache.objtab[oid] = weak.NewRef(obj.persistent())
// XXX assert .pinned[oid] == nil ?
}
}
......@@ -264,7 +264,7 @@ func (cache *LiveCache) forEach(f func(IPersistent)) {
}
for _, wobj := range cache.objtab {
if xobj := wobj.Get(); xobj != nil {
f(xobj.(IPersistent))
f(xobj.instance)
}
}
}
......@@ -280,7 +280,7 @@ func (cache *LiveCache) SetControl(c LiveCacheControl) {
// reclassify all objects
c2 := *cache
cache.objtab = make(map[Oid]*weak.Ref)
cache.objtab = make(map[Oid]*weak.Ref[Persistent])
cache.pinned = make(map[Oid]IPersistent)
c2.forEach(func(obj IPersistent) {
cache.setNew(obj.POid(), obj)
......
......@@ -31,9 +31,10 @@ import (
"sync/atomic"
"time"
"unsafe"
"math/rand"
// "math/rand"
)
/*
// iface is how Go runtime represents an interface.
//
// NOTE layout must be synchronized to Go runtime representation.
......@@ -42,6 +43,7 @@ type iface struct {
typ uintptr // type
data uintptr // data
}
*/
// weakRefState represents current state of an object Ref points to.
type weakRefState int32
......@@ -60,8 +62,10 @@ const (
// There must be no more than 1 weak reference to any object.
// Weak references must not be attached to an object on which runtime.SetFinalizer is also used.
// Weak references must not be copied.
type Ref struct {
iface
type Ref[T any] struct {
// iface
// XXX only one word + reference to go memory model
iptr uintptr // XXX NOTE correctness depends on non-moving property of Go GC
// XXX try to do without mutex and only with atomics
mu sync.Mutex
......@@ -71,12 +75,13 @@ type Ref struct {
// NewRef creates new weak reference pointing to obj.
//
// TODO + onrelease callback?
func NewRef(obj interface{}) *Ref {
func NewRef[T any](obj *T) *Ref[T] {
// since starting from ~ Go1.4 the GC is precise, we can save interface
// pointers to uintptr and that won't prevent GC from garbage
// collecting the object.
w := &Ref{
iface: *(*iface)(unsafe.Pointer(&obj)),
w := &Ref[T]{
// iface: *(*iface)(unsafe.Pointer(&obj)),
iptr: (uintptr)(unsafe.Pointer(obj)),
state: objLive,
}
......@@ -85,10 +90,11 @@ func NewRef(obj interface{}) *Ref {
return w
}
func (w *Ref) release(obj interface{}) {
ifobj := *(*iface)(unsafe.Pointer(&obj))
if w.iface != ifobj {
panic(fmt.Sprintf("weak: release: w.iface != obj; w.iface=%x obj=%x", w.iface, ifobj))
func (w *Ref[T]) release(obj *T) {
// ifobj := *(*iface)(unsafe.Pointer(&obj))
iptr := (uintptr)(unsafe.Pointer(obj))
if w.iptr != iptr {
panic(fmt.Sprintf("weak: release: w.iptr != obj; w.iptr=%x obj=%x", w.iptr, iptr))
}
// GC decided that the object is no longer reachable and
......@@ -115,7 +121,7 @@ var xxx uint64
//
// If original object is still alive - it is returned.
// If not - nil is returned.
func (w *Ref) Get() (obj interface{}) {
func (w *Ref[T]) Get() (obj *T) {
w.mu.Lock()
if w.state != objReleased {
w.state = objGot
......@@ -123,6 +129,13 @@ func (w *Ref) Get() (obj interface{}) {
//time.Sleep(100*time.Nanosecond)
// recreate interface{} from saved words.
// XXX do writes as pointers so that compiler emits write barriers to notify GC?
// recreate pointer from saved word.
obj = (*T)(unsafe.Pointer(w.iptr))
atomic.AddUint64(&xxx, 1) // barrier
time.Sleep(100*time.Nanosecond)
/*
i := (*iface)(unsafe.Pointer(&obj))
//*i = w.iface
......@@ -150,6 +163,7 @@ func (w *Ref) Get() (obj interface{}) {
} else {
i.data = w.iface.data
}
*/
}
w.mu.Unlock()
......
# github.com/DataDog/czlib v0.0.0-20160811164712-4bc9a24e37f2
github.com/DataDog/czlib
## explicit
# github.com/cznic/strutil v0.0.0-20181122101858-275e90344537
github.com/cznic/strutil
## explicit
# github.com/fsnotify/fsnotify v1.4.10-0.20200417215612-7f4cf4dd2b52
github.com/fsnotify/fsnotify
## explicit
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/glog
## explicit
# github.com/kisielk/og-rek v1.0.1-0.20180928202415-8b25c4cefd6c
## explicit
github.com/kisielk/og-rek
# github.com/philhofer/fwd v1.0.0
github.com/philhofer/fwd
## explicit
# github.com/pkg/errors v0.9.1
github.com/pkg/errors
## explicit
# github.com/shamaton/msgpack v1.1.1
## explicit
github.com/shamaton/msgpack
github.com/shamaton/msgpack/def
github.com/shamaton/msgpack/ext
......@@ -23,9 +30,12 @@ github.com/shamaton/msgpack/internal/encoding
github.com/shamaton/msgpack/time
# github.com/someonegg/gocontainer v1.0.0
github.com/someonegg/gocontainer/rbuf
## explicit
# github.com/tinylib/msgp v1.1.3-0.20200327023543-e88e92c0ccca
github.com/tinylib/msgp/msgp
## explicit
# golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
## explicit
golang.org/x/sync/errgroup
# lab.nexedi.com/kirr/go123 v0.0.0-20200916121347-316617668e12
## explicit
......@@ -48,7 +58,7 @@ lab.nexedi.com/kirr/go123/xruntime
lab.nexedi.com/kirr/go123/xstrings
lab.nexedi.com/kirr/go123/xsync
# lab.nexedi.com/kirr/neo/go v0.0.0-20201012044742-28494187df87
## explicit
## explicit; go 1.18
lab.nexedi.com/kirr/neo/go/internal/log
lab.nexedi.com/kirr/neo/go/internal/packed
lab.nexedi.com/kirr/neo/go/internal/task
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment