The locks we have seen are not the same (not both blocking on the same lock).
One is on the FDST (virObjLock)
And the other is on devs->lock of the virChrdevs
priv->devs->lock == fdst->icbOpaque->devs->lock, the assumption is that this is already held by the path undefine takes
Analyzing the backtraces I found crossover locking triggering the deadlock:
I'll call the stack of undefine "U" and the stack of daemonStreamHandleAbort "A":
1A: already has FDST locked in virFDStreamCloseInt
2A: calls virChrdevFDStreamCloseCb which blocks on locks priv->devs->lock
3U: virFDStreamSetInternalCloseCb blocks on locking FDST
4U: virChrdevFree -> ... -> virFDStreamSetInternalCloseCb
5U: virChrdevFree does virMutexLock(&devs->lock);
So it seems that:
- 5U (holds) and 2A (blocks) collide on devs->lock
- 1A (holds) and 3U (blocks) collide on virObjectLock(fdst)
Seems like a classic entangled deadlock :-/
The locks we have seen are not the same (not both blocking on the same lock). ->devs- >lock, the assumption is that this is already held by the path undefine takes
One is on the FDST (virObjLock)
And the other is on devs->lock of the virChrdevs
priv->devs->lock == fdst->icbOpaque
Analyzing the backtraces I found crossover locking triggering the deadlock: dleAbort "A": amCloseCb which blocks on locks priv->devs->lock nternalCloseCb blocks on locking FDST nternalCloseCb &devs-> lock);
I'll call the stack of undefine "U" and the stack of daemonStreamHan
1A: already has FDST locked in virFDStreamCloseInt
2A: calls virChrdevFDStre
3U: virFDStreamSetI
4U: virChrdevFree -> ... -> virFDStreamSetI
5U: virChrdevFree does virMutexLock(
So it seems that:
- 5U (holds) and 2A (blocks) collide on devs->lock
- 1A (holds) and 3U (blocks) collide on virObjectLock(fdst)
Seems like a classic entangled deadlock :-/