13164: Lock tables in order when locking a container.
authorTom Clegg <tclegg@veritasgenetics.com>
Fri, 18 May 2018 18:29:34 +0000 (14:29 -0400)
committerTom Clegg <tclegg@veritasgenetics.com>
Fri, 18 May 2018 18:29:34 +0000 (14:29 -0400)
Locking involves assigning auth_uuid, which involves looking up
container requests, so both tables must be locked in order to avoid
deadlock.

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

services/api/app/models/container.rb

index e9d4f836589cb5933307b869cc6bff8230c894d0..1dbdb571050a70ec3a684f18f335269ac35fd6f8 100644 (file)
@@ -316,11 +316,11 @@ class Container < ArvadosModel
     # (because state might have changed while acquiring the lock).
     check_lock_fail
     transaction do
-      begin
-        reload(lock: 'FOR UPDATE NOWAIT')
-      rescue
-        raise LockFailedError.new("cannot lock: other transaction in progress")
-      end
+      # Locking involves assigning auth_uuid, which involves looking
+      # up container requests, so we must lock both tables in the
+      # proper order to avoid deadlock.
+      ActiveRecord::Base.connection.execute('LOCK container_requests, containers IN EXCLUSIVE MODE')
+      reload
       check_lock_fail
       update_attributes!(state: Locked)
     end