Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/faucet: fix websocket race regression after switching to gorilla #22136

Merged
merged 1 commit into from
Jan 7, 2021

Conversation

karalabe
Copy link
Member

@karalabe karalabe commented Jan 7, 2021

About a year ago we switched over the websocket library in the faucet from Go's implementation to the Gorilla library. Unfortunately the former was thread safe whilst the latter was not, and we didn't update the faucet code to add mutexes. This was undetected for quite a long time since our faucet auto-restarts, so an occasional crash was just silently ignored.

Fixes

panic: concurrent write to websocket connection

goroutine 179 [running]:
github.com/gorilla/websocket.(*messageWriter).flushFrame(0xc01f4879e0, 0x1, 0x0, 0x0, 0x0, 0xc000053c00, 0x0)
	github.com/gorilla/websocket@v1.4.1-0.20190629185528-ae1634f6a989/conn.go:597 +0x60e
github.com/gorilla/websocket.(*messageWriter).Close(0xc01f4879e0, 0x8, 0xc0135d0d28)
	github.com/gorilla/websocket@v1.4.1-0.20190629185528-ae1634f6a989/conn.go:711 +0x65
github.com/gorilla/websocket.(*Conn).beginMessage(0xc002d9e580, 0xc01f487c20, 0x1, 0xc0135d0f68, 0x203007)
	github.com/gorilla/websocket@v1.4.1-0.20190629185528-ae1634f6a989/conn.go:460 +0x262
github.com/gorilla/websocket.(*Conn).NextWriter(0xc002d9e580, 0x1, 0x30, 0xc0135d0e38, 0x7f67fc918538, 0x110)
	github.com/gorilla/websocket@v1.4.1-0.20190629185528-ae1634f6a989/conn.go:500 +0x53
github.com/gorilla/websocket.(*Conn).WriteJSON(0xc002d9e580, 0xf41f60, 0xc01f487bf0, 0x3b9aca00, 0xbff592c9038234b7)
	github.com/gorilla/websocket@v1.4.1-0.20190629185528-ae1634f6a989/json.go:24 +0x49
main.send(0xc002d9e580, 0xf41f60, 0xc01f487bf0, 0x3b9aca00, 0xc01eb75948, 0x2)
	github.com/ethereum/go-ethereum/cmd/faucet/faucet.go:664 +0x8c
main.(*faucet).loop(0xc002d13e00)
	github.com/ethereum/go-ethereum/cmd/faucet/faucet.go:647 +0x2c5
created by main.(*faucet).listenAndServe
	github.com/ethereum/go-ethereum/cmd/faucet/faucet.go:299 +0x45

@karalabe karalabe added this to the 1.10.0 milestone Jan 7, 2021
timeouts map[string]time.Time // History of users and their funding timeouts
reqs []*request // Currently pending funding requests
update chan struct{} // Channel to signal request updates

lock sync.RWMutex // Lock protecting the faucet's internals
}

// wsConn wraps a websocket connection with a write mutex as the underlying
// websocket library does not synchronize access to the stream.
type wsConn struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a similar construct here: https://github.com/ethereum/go-ethereum/blob/master/ethstats/ethstats.go#L100 -- used for ethstats reporting. Would it make sense to use the same?
The other one as a separate lock for reading -- isnt' that needed in this case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure it's worth it.

  • The duplicated code is a couple lines
  • Exposing it in ethstats seems wrong, we'd need to move it into some common package,
  • Ethstats wraps the write directly, but we need setdeadline too wrapped together, so we'd need lower level access.
  • We only read in a dedicated goroutine here, so no need for read locking (though I think it's the same in ethstats).

Copy link
Contributor

@holiman holiman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants