Hi, https://bugs.launchpad.net/ubuntu/+source/dbus-glib/+bug/441190 is what triggered me to look at this. It has the following stacktrace #0 io_handler_watch_freed (data=0x0) at dbus-gmain.c:198 No locals. #1 0x00007fde8af8565b in dbus_watch_set_data (watch=0x24b8090, data=0x0, free_data_function=0) at dbus-watch.c:602 No locals. #2 0x00007fde8af85881 in _dbus_watch_unref (watch=0x0) at dbus-watch.c:131 No locals. #3 0x00007fde8af84e89 in free_watches (transport=0x2305d70) at dbus-transport-socket.c:83 No locals. #4 0x00007fde8af84ee9 in socket_disconnect (transport=0x0) at dbus-transport-socket.c:928 No locals. #5 0x00007fde8af82ea7 in _dbus_transport_disconnect (transport=0x2305d70) at dbus-transport.c:494 No locals. #6 0x00007fde8af838a3 in _dbus_transport_queue_messages (transport=0x2305d70) at dbus-transport.c:1137 status = <value optimized out> It looks to me as though dbus-glib isn't taking part in dbus' reference counting: In dbus, as things are being torn down: _dbus_watch_unref(... . . . if (watch->refcount == 0) { dbus_watch_set_data (watch, NULL, NULL); /* call free_data_function */ which frees the data. in dbus-glib connection_setup_add_watch(... . . . channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch)); handler->source = g_io_create_watch (channel, condition); g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler, io_handler_source_finalized); so io_handler_source_finalized will be called as the watch is torn down io_handler_source_finalized (gpointer data) { IOHandler *handler; handler = data; if (handler->watch) dbus_watch_set_data (handler->watch, NULL, NULL); which frees the data regardless. This isn't a race, the way io_handler_watch_freed is coded, it will crash regardless of the ordering here. I think this isn't an issue for every use, as we are in an exception case in dbus itself: if (_dbus_message_loader_get_is_corrupted (transport->loader)) { _dbus_verbose ("Corrupted message stream, disconnecting\n"); _dbus_transport_disconnect (transport); As for a fix, I'm not sure, should dbus-glib take part in the refcounting, or just not bother freeing the data and rely on dbus to do it? Thanks, James
(In reply to comment #0) > It looks to me as though dbus-glib isn't taking part in dbus' reference > counting: Nothing outside libdbus can take part in DBusWatch refcounting, because _dbus_watch_unref is private to libdbus. > if (watch->refcount == 0) > { > dbus_watch_set_data (watch, NULL, NULL); /* call free_data_function */ ... > if (handler->watch) > dbus_watch_set_data (handler->watch, NULL, NULL); It should be fine that this can be called twice: it's setting the watch's user-data to NULL, but simultaneously setting the user-data free-function to NULL, so the old free-function will only be called on the old user-data, and only once. Also, io_handler_watch_freed sets handler->watch to NULL, and io_handler_source_finalized only calls dbus_watch_set_data if the watch has not been freed; so it can only be called once anyway, as far as I can see. I don't think this crash is necessarily dbus-glib's fault. A regression test would probably be useful: perhaps it could connect a peer-to-peer DBus(G)Connection to a listening Unix socket, and have the listening socket authenticate correctly but then send meaningless data instead of a valid message.
I think this is probably the same thing as Bug #15578 in libdbus; nobody has reproduced that one either. *** This bug has been marked as a duplicate of bug 15578 ***
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.