Using g_signal_connect_data() to attach a destroy notifier that gets called when either the channel or object gets destroyed is clever, but the code is a bit convoluted, as disconnecting one triggers the other. I can't figure out exactly why, but I get memory corruption when unbinding a bunch of properties. For some reason, for one of the properties, the object's destroy notifier appears to run twice. Valgrind reports a bunch of invalid reads and writes.
This new code uses g_object_weak_ref() to watch for the channel and object themselves to be destroyed, and cleans things up that way. The code is more straightforward and I don't get any more memory errors or g_critical messages.