On 07.09.2016 11:41, Maxim Nestratov wrote:
06-Sep-16 17:42, Michal Privoznik пишет:
> On 05.09.2016 18:42, Maxim Nestratov wrote:
>> There is a possibility that qemu driver frees by unreferencing its
>> closeCallbacks pointer as it has the only reference to the object,
>> while in fact not all users of CloseCallbacks called thier
>> virCloseCallbacksUnset.
>>
>> Backtrace is the following:
>> Thread #1:
>> 0 in pthread_cond_wait@(a)GLIBC_2.3.2 () from /lib64/libpthread.so.0
>> 1 in virCondWait (c=<optimized out>, m=<optimized out>)
>> at util/virthread.c:154
>> 2 in virThreadPoolFree (pool=0x7f0810110b50)
>> at util/virthreadpool.c:266
>> 3 in qemuStateCleanup () at qemu/qemu_driver.c:1116
>> 4 in virStateCleanup () at libvirt.c:808
>> 5 in main (argc=<optimized out>, argv=<optimized out>)
>> at libvirtd.c:1660
>>
>> Thread #2:
>> 0 in virClassIsDerivedFrom (klass=0xdeadbeef, parent=0x7f0837c694d0)
>> at util/virobject.c:169
>> 1 in virObjectIsClass (anyobj=anyobj@entry=0x7f08101d4760,
>> klass=<optimized out>) at util/virobject.c:365
>> 2 in virObjectLock (anyobj=0x7f08101d4760) at util/virobject.c:317
>> 3 in virCloseCallbacksUnset (closeCallbacks=0x7f08101d4760,
>> vm=vm@entry=0x7f08101d47b0, cb=cb@entry=0x7f081d078fc0
>> <qemuProcessAutoDestroy>) at util/virclosecallbacks.c:163
>> 4 in qemuProcessAutoDestroyRemove
>> (driver=driver@entry=0x7f081018be50, vm=vm@entry=0x7f08101d47b0) at
>> qemu/qemu_process.c:6368
>> 5 in qemuProcessStop (driver=driver@entry=0x7f081018be50,
>> vm=vm@entry=0x7f08101d47b0,
>> reason=reason@entry=VIR_DOMAIN_SHUTOFF_SHUTDOWN,
>> asyncJob=asyncJob@entry=QEMU_ASYNC_JOB_NONE, flags=flags@entry=0) at
>> qemu/qemu_process.c:5854
>> 6 in processMonitorEOFEvent (vm=0x7f08101d47b0,
>> driver=0x7f081018be50) at qemu/qemu_driver.c:4585
>> 7 qemuProcessEventHandler (data=<optimized out>,
>> opaque=0x7f081018be50) at qemu/qemu_driver.c:4629
>> 8 in virThreadPoolWorker (opaque=opaque@entry=0x7f0837c4f820) at
>> util/virthreadpool.c:145
>> 9 in virThreadHelper (data=<optimized out>) at util/virthread.c:206
>> 10 in start_thread () from /lib64/libpthread.so.0
>>
>> Let's reference CloseCallbacks object in virCloseCallbacksSet and
>> unreference in virCloseCallbacksUnset.
>>
>> Signed-off-by: Maxim Nestratov <mnestratov(a)virtuozzo.com>
>> ---
>> src/util/virclosecallbacks.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/src/util/virclosecallbacks.c b/src/util/virclosecallbacks.c
>> index 82d4071..891a92b 100644
>> --- a/src/util/virclosecallbacks.c
>> +++ b/src/util/virclosecallbacks.c
>> @@ -141,6 +141,7 @@ virCloseCallbacksSet(virCloseCallbacksPtr
>> closeCallbacks,
>> virObjectRef(vm);
>> }
>> + virObjectRef(closeCallbacks);
>> ret = 0;
>> cleanup:
>> virObjectUnlock(closeCallbacks);
>> @@ -180,6 +181,8 @@ virCloseCallbacksUnset(virCloseCallbacksPtr
>> closeCallbacks,
>> ret = 0;
>> cleanup:
>> virObjectUnlock(closeCallbacks);
>> + if (!ret)
>> + virObjectUnref(closeCallbacks);
> Might as well put this a few lines above, just before 'ret = 0' line.
>
> ACK with that changed.
>
> Michal
No, we can't do this, as it could be the last reference to
closeCallbacks and after derefencing it, virObjectUnlock would touch
freed memory.
Ah, good point. Stick to the original then.
Michal