capnproto / go-capnp

Cap'n Proto library and code generator for Go

Home Page:https://capnproto.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ReleaseFunc from importClient.Send panics

lthibault opened this issue · comments

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x11dbfe6]
goroutine 368 [running]:
capnproto.org/go/capnp/v3/rpc.(*importClient).Send.func4()
        capnproto.org/go/capnp/v3@v3.0.0-alpha.2/rpc/import.go:127 +0x46
github.com/wetware/ww/pkg/cap/pubsub.Topic.Publish({0xc13f5ac000?}, {0x225cbe0, 0xc006861dc0}, {0xc13f64e000, 0x707c1, 0xa12a8})
        github.com/wetware/ww@v0.0.0-alpha.2/pkg/cap/pubsub/client.go:52 +0x11a
github.com/wetware/ww/pkg/client.(*futureTopic).Publish(0xc1233c9300?, {0x225cbe0, 0xc006861dc0}, {0xc13f64e000, 0x707c1, 0xa12a8})
        github.com/wetware/ww@v0.0.0-alpha.2/pkg/client/pubsub.go:44 +0x54
github.com/ethereum/go-ethereum/eth.publisher.Publish({{0x2260480?, 0xc0138f60f0?}}, {0x225cbe0, 0xc006861dc0}, 0x339cf20?)
        github.com/ethereum/go-ethereum/eth/wetware.go:224 +0x72
github.com/ethereum/go-ethereum/eth.(*wetware).publishPendingTx.func1()
        github.com/ethereum/go-ethereum/eth/wetware.go:179 +0x652
golang.org/x/sync/errgroup.(*Group).Go.func1()
        golang.org/x/sync@v0.0.0-20210220032951-036812b2e83c/errgroup/errgroup.go:57 +0x67
created by golang.org/x/sync/errgroup.(*Group).Go
        golang.org/x/sync@v0.0.0-20210220032951-036812b2e83c/errgroup/errgroup.go:54 +0x8d

I encountered the above panic in a production environment that streams a moderately large volume of data (several hundred items per second, with each item averaging around 70kb).

The stack trace bottoms out in importClient.Send, on line 127, which is the last line of the following release function:

return ans, func() {
	<-ans.Done()
	q.p.ReleaseClients()
	q.release()  // PANIC
}

@zenhack Is there something the client code could be doing incorrectly that would cause q.release to be nil?

@zenhack I see the comment following comment in question.go:

type question struct {
	// ...
	release capnp.ReleaseFunc // written before resolving p
	// ...
}

This suggests to me that question starts its lifecycle without a release function. Maybe we're forgetting to set it somewhere?

Maybe. I'd have to dig into the code to provide much extra insight, but I vaguely recall there were a bunch of places where we set:

q.release = func() { }

...so maybe we missed a spot?

Could this be happening in handleReturn due to that new goroutine? Perhaps something is trying to call q.release() before q.release = func() { } executes?

That seems plausible.

I haven't seen this one in a while. Closing optimistically.