diff options
author | Jeremy Daer <jeremydaer@gmail.com> | 2016-02-01 12:20:44 -0700 |
---|---|---|
committer | Jeremy Daer <jeremydaer@gmail.com> | 2016-02-01 14:12:49 -0700 |
commit | 8fd123f7ebf938d21c1a097561950c6d7e1213bb (patch) | |
tree | d5ae1ec792b4329ff511b1e3ae1b56529b44610e /activemodel/lib/active_model/validations/validates.rb | |
parent | 4f2bce959b24fa519307c21481c240b9d35d9540 (diff) | |
download | rails-8fd123f7ebf938d21c1a097561950c6d7e1213bb.tar.gz rails-8fd123f7ebf938d21c1a097561950c6d7e1213bb.tar.bz2 rails-8fd123f7ebf938d21c1a097561950c6d7e1213bb.zip |
Fix corrupt transaction state caused by `before_commit` exceptions
When a `before_commit` callback raises, the database is rolled back but
AR's record of the current transaction is not, leaving the connection in
a perpetually broken state that affects all future users of the
connection: subsequent requests, jobs, etc. They'll think a transaction
is active when none is, so they won't BEGIN on their own. This manifests
as missing `after_commit` callbacks and broken ROLLBACKs.
This happens because `before_commit` callbacks fire before the current
transaction is popped from the stack, but the exception-handling path
they hit assumes that the current transaction was already popped. So the
database ROLLBACK is issued, but the transaction stack is left intact.
Common cause: deadlocked `#touch`, which is now implemented with
`before_commit` callbacks.
What's next:
* We shouldn't allow active transaction state when checking in or out
from the connection pool. Verify that conns are clean.
* Closer review of txn manager sad paths. Are we missing other spots
where we'd end up with incorrect txn state? What's the worst that can
happen if txn state drifts? How can we guarantee it doesn't and
contain the fallout if it does?
Thanks for @tomafro for expert diagnosis!
Diffstat (limited to 'activemodel/lib/active_model/validations/validates.rb')
0 files changed, 0 insertions, 0 deletions