So, there’s all this magic with handling errClosed, having wrapper snapshot types and wrapper iterator types and now I’d need wrapper transaction types etc. Can we not just wait for all services to shut down before closing the database, and ensure similar things in tests? At the moment I’m suffering backtraces like these which took me a few minutes to figure out WTF it’s saying
fatal error: sync: Unlock of unlocked RWMutex
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4748c76]
goroutine 335 [running]:
runtime.throw(0x4c36cb7, 0x20)
/usr/local/go/src/runtime/panic.go:617 +0x72 fp=0xc00a1db030 sp=0xc00a1db000 pc=0x402fb82
sync.throw(0x4c36cb7, 0x20)
/usr/local/go/src/runtime/panic.go:603 +0x35 fp=0xc00a1db050 sp=0xc00a1db030 pc=0x402fb05
sync.(*RWMutex).Unlock(0xc0000e4140)
/usr/local/go/src/sync/rwmutex.go:124 +0xeb fp=0xc00a1db090 sp=0xc00a1db050 pc=0x408010b
runtime.call32(0x0, 0x4daecf0, 0xc00015f4b0, 0x800000008)
/usr/local/go/src/runtime/asm_amd64.s:519 +0x3b fp=0xc00a1db0c0 sp=0xc00a1db090 pc=0x405e31b
panic(0x4b50ec0, 0x53da110)
/usr/local/go/src/runtime/panic.go:522 +0x1b5 fp=0xc00a1db150 sp=0xc00a1db0c0 pc=0x402f6b5
runtime.panicmem(...)
/usr/local/go/src/runtime/panic.go:82
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:390 +0x411 fp=0xc00a1db180 sp=0xc00a1db150 pc=0x4046421
github.com/syndtr/goleveldb/leveldb.(*Transaction).Commit(0x0, 0x0, 0x0)
/Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v1.0.1-0.20190318030020-c3a204f8e965/leveldb/db_transaction.go:191 +0x56 fp=0xc00a1db310 sp=0xc00a1db180 pc=0x4748c76
github.com/syncthing/syncthing/lib/db.readWriteTransaction.close(0x4dab700, 0x0, 0x0)
/Users/jb/dev/github.com/syncthing/syncthing/lib/db/transactions.go:152 +0x3d fp=0xc00a1db350 sp=0xc00a1db310 pc=0x47a955d
runtime.call32(0x0, 0x4c52778, 0xc00064c9e0, 0x1800000018)
/usr/local/go/src/runtime/asm_amd64.s:519 +0x3b fp=0xc00a1db380 sp=0xc00a1db350 pc=0x405e31b
panic(0x4b50ec0, 0x53da110)
/usr/local/go/src/runtime/panic.go:522 +0x1b5 fp=0xc00a1db410 sp=0xc00a1db380 pc=0x402f6b5
runtime.panicmem(...)
/usr/local/go/src/runtime/panic.go:82
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:390 +0x411 fp=0xc00a1db440 sp=0xc00a1db410 pc=0x4046421
github.com/syndtr/goleveldb/leveldb.(*Transaction).NewIterator(0x0, 0xc003f23b00, 0x0, 0x0, 0x0)
/Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v1.0.1-0.20190318030020-c3a204f8e965/leveldb/db_transaction.go:80 +0x53 fp=0xc00a1db4e8 sp=0xc00a1db440 pc=0x47471a3
github.com/syncthing/syncthing/lib/db.(*readWriteTransaction).NewIterator(0xc0000b5580, 0xc003f23b00, 0x0, 0xc003f23b00, 0x0)
<autogenerated>:1 +0x7b fp=0xc00a1db538 sp=0xc00a1db4e8 pc=0x47b506b
github.com/syncthing/syncthing/lib/db.checkGlobals(0x4db3880, 0xc0000b5580, 0x4dbd860, 0xc003f208a0, 0xc000636d28, 0x7, 0x8, 0xc00015fcc0)
/Users/jb/dev/github.com/syncthing/syncthing/lib/db/instance.go:472 +0x14a fp=0xc00a1db898 sp=0xc00a1db538 pc=0x478243a
github.com/syncthing/syncthing/lib/db.(*instance).checkGlobals(0xc0000b5560, 0xc000636d28, 0x7, 0x8, 0xc00015fcc0)
/Users/jb/dev/github.com/syncthing/syncthing/lib/db/instance.go:468 +0x165 fp=0xc00a1db918 sp=0xc00a1db898 pc=0x47822b5
github.com/syncthing/syncthing/lib/db.(*FileSet).recalcCounts(0xc00015fc40)
/Users/jb/dev/github.com/syncthing/syncthing/lib/db/set.go:94 +0x231 fp=0xc00a1db9f8 sp=0xc00a1db918 pc=0x478fdc1
github.com/syncthing/syncthing/lib/db.NewFileSet(0x4c251e6, 0x7, 0x4dbf480, 0xc00a124230, 0xc0001f20f0, 0x4c25ab3)
/Users/jb/dev/github.com/syncthing/syncthing/lib/db/set.go:82 +0x4f0 fp=0xc00a1dbb18 sp=0xc00a1db9f8 pc=0x478f8d0
github.com/syncthing/syncthing/lib/model.(*model).RestartFolder(0xc001244000, 0x4c251e6, 0x7, 0x0, 0x0, 0x0, 0x4c25ab3, 0x8, 0x0, 0xc00a0d3800, ...)
/Users/jb/dev/github.com/syncthing/syncthing/lib/model/model.go:470 +0x84b fp=0xc00a1dc3f0 sp=0xc00a1dbb18 pc=0x499534b
github.com/syncthing/syncthing/lib/model.(*model).CommitConfiguration(0xc001244000, 0x0, 0xc000f4db80, 0x2, 0x2, 0xc00a11f3b0, 0x1, 0x1, 0x0, 0x0, ...)
/Users/jb/dev/github.com/syncthing/syncthing/lib/model/model.go:2518 +0xe35 fp=0xc00a1de388 sp=0xc00a1dc3f0 pc=0x49b6575
github.com/syncthing/syncthing/lib/config.(*wrapper).notifyListener(0xc0011f6000, 0x4dab080, 0xc001244000, 0x0, 0xc000f4db80, 0x2, 0x2, 0xc00a11f3b0, 0x1, 0x1, ...)
/Users/jb/dev/github.com/syncthing/syncthing/lib/config/wrapper.go:239 +0x20d fp=0xc00a1df1a0 sp=0xc00a1de388 pc=0x46dddbd
github.com/syncthing/syncthing/lib/config.(*wrapper).notifyListeners.func1(0xc0011f6000, 0xc0011af880, 0xc0011afc00, 0x4dabc00, 0xc00a1148d0, 0x4dab080, 0xc001244000)
/Users/jb/dev/github.com/syncthing/syncthing/lib/config/wrapper.go:230 +0x166 fp=0xc00a1dffa8 sp=0xc00a1df1a0 pc=0x46e5506
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc00a1dffb0 sp=0xc00a1dffa8 pc=0x4060011
created by github.com/syncthing/syncthing/lib/config.(*wrapper).notifyListeners
/Users/jb/dev/github.com/syncthing/syncthing/lib/config/wrapper.go:229 +0x2a7
because I’m not correctly handling the fact that the database might be closed and yet we’re calling newReadWriteTransaction
on it (and have no error return)…
I guess another option is to take the bull by the horn and bubble all errors? At the highest level that should result in some Serve()
returning when it can’t handle it, which is the desirable result anyway…