[libvirt] [PATCH] virConnectUnregisterCloseCallback: Unlock @conn prior to error dispatch

The function checks for @conn to be valid and locks its mutex. Then, it checks if callee is unregistering the same callback that he registered previously. If this fails an error is reported and the control jumps to 'error' label. Here, if @conn has some errors (and it certainly does - the one that's been just reported) the conn->mutex is locked again - without any previous unlock: Thread 1 (Thread 0x7fb500ef1800 (LWP 18982)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 #1 0x00007fb4fd99ce56 in _L_lock_918 () from /lib64/libpthread.so.0 #2 0x00007fb4fd99ccaa in __GI___pthread_mutex_lock (mutex=0x7fb50153b670) at pthread_mutex_lock.c:64 #3 0x00007fb5007e574d in virMutexLock (m=m@entry=0x7fb50153b670) at util/virthreadpthread.c:85 #4 0x00007fb5007b198e in virDispatchError (conn=conn@entry=0x7fb50153b5e0) at util/virerror.c:594 #5 0x00007fb5008a3735 in virConnectUnregisterCloseCallback (conn=0x7fb50153b5e0, cb=cb@entry=0x7fb500f588e0 <vshCatchDisconnect>) at libvirt.c:21025 #6 0x00007fb500f5d690 in vshReconnect (ctl=ctl@entry=0x7fffff60e710) at virsh.c:328 #7 0x00007fb500f5dc50 in vshCommandRun (ctl=ctl@entry=0x7fffff60e710, cmd=0x7fb50152ca80) at virsh.c:1755 #8 0x00007fb500f5861b in main (argc=<optimized out>, argv=<optimized out>) at virsh.c:3393 And since the conn's mutex is not recursive, the virDispatchError will never ever lock it successfully. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvirt.c b/src/libvirt.c index 2f5f023..71c9d8c 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -21022,9 +21022,9 @@ virConnectUnregisterCloseCallback(virConnectPtr conn, return 0; error: - virDispatchError(conn); virObjectUnlock(conn->closeCallback); virMutexUnlock(&conn->lock); + virDispatchError(conn); return -1; } -- 1.8.5.1

On 01/07/2014 10:25 AM, Michal Privoznik wrote:
The function checks for @conn to be valid and locks its mutex. Then, it checks if callee is unregistering the same callback that he registered previously. If this fails an error is reported and the control jumps to 'error' label. Here, if @conn has some errors (and it certainly does - the one that's been just reported) the conn->mutex is locked again - without any previous unlock:
ACK; bug introduced in commit ca0ea2a.
+++ b/src/libvirt.c @@ -21022,9 +21022,9 @@ virConnectUnregisterCloseCallback(virConnectPtr conn, return 0;
error: - virDispatchError(conn); virObjectUnlock(conn->closeCallback); virMutexUnlock(&conn->lock); + virDispatchError(conn); return -1; }
-- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 07.01.2014 18:42, Eric Blake wrote:
On 01/07/2014 10:25 AM, Michal Privoznik wrote:
The function checks for @conn to be valid and locks its mutex. Then, it checks if callee is unregistering the same callback that he registered previously. If this fails an error is reported and the control jumps to 'error' label. Here, if @conn has some errors (and it certainly does - the one that's been just reported) the conn->mutex is locked again - without any previous unlock:
ACK; bug introduced in commit ca0ea2a.
AHA! In that case this patch is incomplete as looking at the blamed commit I've found another candidate worth fixing (even though I have not experienced any deadlock in it yet): virConnectRegisterCloseCallback(). I've squashed this in prior to push: diff --git a/src/libvirt.c b/src/libvirt.c index 1f5590f..619da80 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -20446,9 +20446,9 @@ virConnectRegisterCloseCallback(virConnectPtr conn, return 0; error: - virDispatchError(conn); virObjectUnlock(conn->closeCallback); virMutexUnlock(&conn->lock); + virDispatchError(conn); virObjectUnref(conn); return -1; } Thanks! Michal
participants (2)
-
Eric Blake
-
Michal Privoznik