[libvirt] [PATCH] do not send monitor command after monitor met error

Wen Congyang wency at cn.fujitsu.com
Wed Mar 30 07:36:54 UTC 2011


At 03/29/2011 05:59 PM, Daniel P. Berrange Write:
> On Tue, Mar 29, 2011 at 03:22:40PM +0800, Wen Congyang wrote:
>> If the monitor met a error, and we will call qemuProcessHandleMonitorEOF().
>> But we may try to send monitor command after qemuProcessHandleMonitorEOF()
>> returned. Then libvirtd will be blocked in qemuMonitorSend().
>>
>> Steps to reproduce this bug:
>> 1. use gdb to attach libvirtd, and set a breakpoint in the function
>>    qemuConnectMonitor()
>> 2. start a vm
>> 3. let the libvirtd to run until qemuMonitorOpen() returns.
>> 4. kill the qemu process
>> 5. continue running libvirtd
>>
>> Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
>>
>> ---
>>  src/qemu/qemu_monitor.c |   13 +++++++++++++
>>  1 files changed, 13 insertions(+), 0 deletions(-)
>>
>> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
>> index 800f744..eed83f4 100644
>> --- a/src/qemu/qemu_monitor.c
>> +++ b/src/qemu/qemu_monitor.c
>> @@ -572,6 +572,13 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
>>                  mon->msg->lastErrno = EIO;
>>                  virCondSignal(&mon->notify);
>>              }
>> +            /* If qemu quited unexpectedly, and we may try to send monitor
>> +             * command later. But we have no chance to wake up it. So set
>> +             * mon->lastErrno to EIO, and check it before sending monitor
>> +             * command.
>> +             */
>> +            if (!mon->lastErrno)
>> +                mon->lastErrno = EIO;
>>              quit = 1;
>>          } else if (events) {
>>              VIR_ERROR(_("unhandled fd event %d for monitor fd %d"),
> 
> I'm wondering if we should just move this safety check a little
> further down in this method, because the 'else if (events)' branch
> likely wants this check too.
> 
> eg I'd put it in the bit where we run the EOF callback something
> like this:
> 
>     /* We have to unlock to avoid deadlock against command thread,
>      * but is this safe ?  I think it is, because the callback
>      * will try to acquire the virDomainObjPtr mutex next */
>     if (failed || quit) {
>         void (*eofNotify)(qemuMonitorPtr, virDomainObjPtr, int)
>             = mon->cb->eofNotify;
>         virDomainObjPtr vm = mon->vm;
> 
> +       /* If qemu quited unexpectedly, and we may try to send monitor
> +        * command later. But we have no chance to wake up it. So set
> +        * mon->lastErrno to EIO, and check it before sending monitor
> +        * command.
> +        */
> +       if (!mon->lastErrno)
> +         mon->lastErrno = EIO;

Yes, setting mon->lastErrno here is better.

Pushed with this fixed. Thanks.

> 
>         /* Make sure anyone waiting wakes up now */
>         virCondSignal(&mon->notify);
>         if (qemuMonitorUnref(mon) > 0)
>             qemuMonitorUnlock(mon);
>         VIR_DEBUG("Triggering EOF callback error? %d", failed);
>         (eofNotify)(mon, vm, failed);
> 
> 
>> @@ -725,6 +732,12 @@ int qemuMonitorSend(qemuMonitorPtr mon,
>>  {
>>      int ret = -1;
>>  
>> +    /* Check whether qemu quited unexpectedly */
>> +    if (mon->lastErrno) {
>> +        msg->lastErrno = mon->lastErrno;
>> +        return -1;
>> +    }
>> +
>>      mon->msg = msg;
>>      qemuMonitorUpdateWatch(mon);
> 
> 
> Daniel




More information about the libvir-list mailing list