You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, the Get and Select iterx methods call iter.ReleaseQuery(). This is a highly dangerous "convenience" which can lead to data races under common usage patterns.
The Iter constructor and Get and Select functions accept a query as a parameter, and so from an API design perspective it make most sense to let clients (who created the query) manage the query lifecycle.
E.g. it's a pretty common pattern to do
q := createQuery()
defer q.Release()
// do stuff with query, err returns, etc
return result, nil
But if "doing stuff" includes a gocqlx.Select, this pattern will lead to Release being called twice. That means the query object now has two entries in the query pool, which will distribute it to two separate goroutines, and racy concurrent read/writes ensue. We had a very hard-to-track-down bug in our service caused by this.
In this case, the cost of not calling Release is minimal; the query will just be GC'd instead of recycled. It's safer and better to let clients do releasing themselves.
The text was updated successfully, but these errors were encountered:
jgiles
added a commit
to paxosglobal/DEPRECATED-gocqlx
that referenced
this issue
Nov 6, 2017
Releasing query objects in Get/Select could easily lead to
double-releases, which can cause dangerous and tricky data races.
Remove the query field of Iterx and its usages (all release-related).
This is a breaking API change, because it removes the exported method
ReleaseQuery.
Update documenting examples to demonstrate the deferred query release
pattern clients can use to manage query release.
Currently, the
Get
andSelect
iterx methods calliter.ReleaseQuery()
. This is a highly dangerous "convenience" which can lead to data races under common usage patterns.The
Iter
constructor andGet
andSelect
functions accept a query as a parameter, and so from an API design perspective it make most sense to let clients (who created the query) manage the query lifecycle.E.g. it's a pretty common pattern to do
But if "doing stuff" includes a
gocqlx.Select
, this pattern will lead toRelease
being called twice. That means the query object now has two entries in the query pool, which will distribute it to two separate goroutines, and racy concurrent read/writes ensue. We had a very hard-to-track-down bug in our service caused by this.In this case, the cost of not calling Release is minimal; the query will just be GC'd instead of recycled. It's safer and better to let clients do releasing themselves.
The text was updated successfully, but these errors were encountered: