On Mon, Jun 25, 2012 at 11:03:16AM +0100, Daniel P. Berrange wrote:
On Wed, Jun 20, 2012 at 12:29:51PM +0200, Christophe Fergeau wrote:
> The deletion of libvirt timeouts/watches is done in 2 steps:
> - the first step is synchronous and unregisters the timeout/watch
> from glib mainloop
> - the second step is asynchronous and triggered from the first step.
> It releases the memory used for bookkeeping for the timeout/watch
> being deleted
>
> This is done this way to avoid some possible deadlocks when
> reentering the sync callback while freeing the memory associated
> with the timeout/watch.
>
> However, it's possible to call gvir_event_update_handle after
> gvir_event_remove_handle but before _event_handle_remove does
> the final cleanup. When this happen, _update_handle will reregister
> the handle with glib mainloop, and bad things will happen when
> a glib callback is triggered for this event after _event_handle_remove
> has freed the memory associated with this handle watch.
That's clearly possible, but it is also illegal use of the events
API by some client code, since the timer/watch id is not valid
after calling remove(). Do you actually see this occurring in
real life ?
Yes, I've seen this with gnome-boxes when starting a VM and then letting it
run in the background, see the cover letter for a few more details
I've just added
if (h->removed)
G_BREAKPOINT;
to gvir_event_timeout_find to catch a backtrace when this happens:
(gdb) bt
#0 gvir_event_handle_find (watch=1) at libvirt-glib-event.c:202
#1 0x00007ffff6670b78 in gvir_event_handle_update (watch=1, events=1)
at libvirt-glib-event.c:218
#2 0x00007ffff5f400e9 in virEventUpdateHandle (watch=1, events=1)
at util/event.c:70
#3 0x00007ffff60823f1 in virNetSocketUpdateIOCallback
(sock=0x7fffdc001fe0,
events=1) at rpc/virnetsocket.c:1384
#4 0x00007ffff606e74e in virNetClientIOUpdateCallback
(client=0x7fffdc001e20,
enableCallback=true) at rpc/virnetclient.c:1454
#5 0x00007ffff606ecec in virNetClientIncomingEvent (sock=0x7fffdc001fe0,
events=2, opaque=0x7fffdc001e20) at rpc/virnetclient.c:1659
#6 0x00007ffff608213c in virNetSocketEventHandle (watch=1, fd=26,
events=2,
opaque=0x7fffdc001fe0) at rpc/virnetsocket.c:1314
#7 0x00007ffff66708cd in gvir_event_handle_dispatch
(source=0x7fffdc001f60,
condition=G_IO_OUT, opaque=0x7fffdc001930) at libvirt-glib-event.c:136
#8 0x00007ffff1e20cb4 in g_io_unix_dispatch (source=0x7fffdc0017d0,
callback=0x7ffff66707f8 <gvir_event_handle_dispatch>,
user_data=0x7fffdc001930) at giounix.c:166
#9 0x00007ffff1dd1f15 in g_main_dispatch (context=0x6fea30) at
gmain.c:2539
#10 0x00007ffff1dd2bda in g_main_context_dispatch (context=0x6fea30)
at gmain.c:3075
#11 0x00007ffff1dd2dbd in g_main_context_iterate (context=0x6fea30,
block=1,
dispatch=1, self=0x728780) at gmain.c:3146
#12 0x00007ffff1dd2e81 in g_main_context_iteration (context=0x6fea30,
may_block=1) at gmain.c:3207
#13 0x00007ffff25dbe7c in g_application_run (application=0x709890, argc=0,
argv=0x0) at gapplication.c:1607
#14 0x000000000041dec8 in boxes_app_run (self=0x1525010) at app.c:1187
#15 0x00000000004506f4 in _vala_main (args=0x7fffffffd738, args_length1=1)
at main.c:729
#16 0x000000000045075e in main (argc=1, argv=0x7fffffffd738) at main.c:740
It happens at more or less random times, so I'm not sure if I'll be able to
catch a backtrace when the watch is removed.
Christophe