Patchwork [05/18] vl.c: add deleted flag for deleting the handler.

login
register
mail settings
Submitter Yoshiaki Tamura
Date Feb. 23, 2011, 1:48 p.m.
Message ID <1298468927-19193-6-git-send-email-tamura.yoshiaki@lab.ntt.co.jp>
Download mbox | patch
Permalink /patch/84173/
State New
Headers show

Comments

Yoshiaki Tamura - Feb. 23, 2011, 1:48 p.m.
Make deleting handlers robust against deletion of any elements in a
handler by using a deleted flag like in file descriptors.

Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki@lab.ntt.co.jp>
---
 vl.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)
Juan Quintela - Feb. 23, 2011, 10:04 p.m.
Yoshiaki Tamura <tamura.yoshiaki@lab.ntt.co.jp> wrote:
> Make deleting handlers robust against deletion of any elements in a
> handler by using a deleted flag like in file descriptors.
>
> Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki@lab.ntt.co.jp>
> ---
>  vl.c |   13 +++++++++----
>  1 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/vl.c b/vl.c
> index b436952..4e263c3 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1158,6 +1158,7 @@ static void nographic_update(void *opaque)
>  struct vm_change_state_entry {
>      VMChangeStateHandler *cb;
>      void *opaque;
> +    int deleted;
>      QLIST_ENTRY (vm_change_state_entry) entries;
>  };
>  
> @@ -1178,8 +1179,7 @@ VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
>  
>  void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
>  {
> -    QLIST_REMOVE (e, entries);
> -    qemu_free (e);
> +    e->deleted = 1;
>  }
>  
>  void vm_state_notify(int running, int reason)
> @@ -1188,8 +1188,13 @@ void vm_state_notify(int running, int reason)
>  
>      trace_vm_state_notify(running, reason);
>  
> -    for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
> -        e->cb(e->opaque, running, reason);

this needs to become:

> +    QLIST_FOREACH(e, &vm_change_state_head, entries) {
> +        if (e->deleted) {
> +            QLIST_REMOVE(e, entries);
> +            qemu_free(e);
> +        } else {
> +            e->cb(e->opaque, running, reason);
> +        }

   VMChangeState_entry *next;

   QLIST_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
      .....

  Otherwise you are accessing "e" after qemu_free and being put out of
  the list.

Later, Juan.
Yoshiaki Tamura - Feb. 24, 2011, 2:47 a.m.
Juan Quintela wrote:
> Yoshiaki Tamura<tamura.yoshiaki@lab.ntt.co.jp>  wrote:
>> Make deleting handlers robust against deletion of any elements in a
>> handler by using a deleted flag like in file descriptors.
>>
>> Signed-off-by: Yoshiaki Tamura<tamura.yoshiaki@lab.ntt.co.jp>
>> ---
>>   vl.c |   13 +++++++++----
>>   1 files changed, 9 insertions(+), 4 deletions(-)
>>
>> diff --git a/vl.c b/vl.c
>> index b436952..4e263c3 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -1158,6 +1158,7 @@ static void nographic_update(void *opaque)
>>   struct vm_change_state_entry {
>>       VMChangeStateHandler *cb;
>>       void *opaque;
>> +    int deleted;
>>       QLIST_ENTRY (vm_change_state_entry) entries;
>>   };
>>
>> @@ -1178,8 +1179,7 @@ VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
>>
>>   void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
>>   {
>> -    QLIST_REMOVE (e, entries);
>> -    qemu_free (e);
>> +    e->deleted = 1;
>>   }
>>
>>   void vm_state_notify(int running, int reason)
>> @@ -1188,8 +1188,13 @@ void vm_state_notify(int running, int reason)
>>
>>       trace_vm_state_notify(running, reason);
>>
>> -    for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
>> -        e->cb(e->opaque, running, reason);
>
> this needs to become:
>
>> +    QLIST_FOREACH(e,&vm_change_state_head, entries) {
>> +        if (e->deleted) {
>> +            QLIST_REMOVE(e, entries);
>> +            qemu_free(e);
>> +        } else {
>> +            e->cb(e->opaque, running, reason);
>> +        }
>
>     VMChangeState_entry *next;
>
>     QLIST_FOREACH_SAFE(e,&vm_change_state_head, entries, next) {
>        .....
>
>    Otherwise you are accessing "e" after qemu_free and being put out of
>    the list.

You're right.  Thanks.

Yoshi

>
> Later, Juan.
>

Patch

diff --git a/vl.c b/vl.c
index b436952..4e263c3 100644
--- a/vl.c
+++ b/vl.c
@@ -1158,6 +1158,7 @@  static void nographic_update(void *opaque)
 struct vm_change_state_entry {
     VMChangeStateHandler *cb;
     void *opaque;
+    int deleted;
     QLIST_ENTRY (vm_change_state_entry) entries;
 };
 
@@ -1178,8 +1179,7 @@  VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
 
 void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
 {
-    QLIST_REMOVE (e, entries);
-    qemu_free (e);
+    e->deleted = 1;
 }
 
 void vm_state_notify(int running, int reason)
@@ -1188,8 +1188,13 @@  void vm_state_notify(int running, int reason)
 
     trace_vm_state_notify(running, reason);
 
-    for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
-        e->cb(e->opaque, running, reason);
+    QLIST_FOREACH(e, &vm_change_state_head, entries) {
+        if (e->deleted) {
+            QLIST_REMOVE(e, entries);
+            qemu_free(e);
+        } else {
+            e->cb(e->opaque, running, reason);
+        }
     }
 }