So... I was reviewing some code today, and was getting annoyed that _gabble_connection_send_with_reply() can return either synchronously or asynchronously. So I had a poke at its implementation.
• _gabble_connection_send_with_reply() calls lm_connection_send_with_reply().
• lm_connection_send_with_reply() calls wocky_porter_send_iq_async, passing iq_reply_cb() as the callback.
• iq_reply_cb() in lib/loudmouth/lm-connection.c calls wocky_porter_send_iq_finish(), and if it gets no reply, does not call the callback passed to _gabble_connection_send_with_reply()! So if you get disconnected, your callback will never be called, and we leak and/or die later.
I took a look at about half of the callbacks passed to _gabble_connection_send_with_reply() — it's actually only called 37 times — and the callbacks do indeed all assume that the reply message is not NULL. So... this seems pretty broken to me.
I think the right fix is to just remove one or more layers of wrapper around wocky_porter_send_iq_async(), to be honest.