Skip to content

Commit c4893c7

Browse files
committed
Fix deadlock during NRI plugin registration
During NRI external plugin registration: * `acceptPluginConnections()` is called * adaptation lock from `nri/pkg/adaptation` is acquired * `syncFn` is invoked * `syncFn` acquires NRI lock in `pkg/nri/nri.go` During container lifecycle events such as `ContainerStart` * NRI lock is acquired in pkg/nri.go * adaptation lock is acquired in `StateChange()` in `nri/pkg/adaptation` As a result, the locking order during NRI plugin registration is: * adaptation lock -> NRI lock While the locking order during container starts is: * NRI lock -> adaptation lock Due the fact that the locking order is inverted and not consistent, it it possible to encounter a deadlock. To fix the issue, during NRI plugin registration, first acquire the NRI lock (done via `syncFn` call) and only after acquire the adaptation lock. This ensures that NRI plugin registration the locking order is adaption lock -> NRI lock, which is consistent with the locking order during container lifecycle events. Fixes containerd/containerd#10085 Signed-off-by: David Porter <[email protected]>
1 parent 53d3371 commit c4893c7

1 file changed

Lines changed: 2 additions & 4 deletions

File tree

pkg/adaptation/adaptation.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,18 +431,16 @@ func (r *Adaptation) acceptPluginConnections(l net.Listener) error {
431431
continue
432432
}
433433

434-
r.Lock()
435-
436434
err = r.syncFn(ctx, p.synchronize)
437435
if err != nil {
438436
log.Infof(ctx, "failed to synchronize plugin: %v", err)
439437
} else {
438+
r.Lock()
440439
r.plugins = append(r.plugins, p)
441440
r.sortPlugins()
441+
r.Unlock()
442442
}
443443

444-
r.Unlock()
445-
446444
log.Infof(ctx, "plugin %q connected", p.name())
447445
}
448446
}()

0 commit comments

Comments
 (0)