
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