Don't free connection internals before it's closed. [#34]
When the connection freed up internal states (in this case the handler
lists) before closing itself it segfaulted when trying to unregister the
SASL handlers.
Reported by Julien Puydt.
--- a/loudmouth/lm-connection.c Wed Nov 19 10:16:40 2008 +0100
+++ b/loudmouth/lm-connection.c Sun Nov 30 09:27:21 2008 +0100
@@ -191,13 +191,21 @@
{
int i;
+ /* This needs to be run before starting to free internal states.
+ * It used to be run after the handlers where freed which lead to a crash
+ * when the connection was freed prior to running lm_connection_close.
+ */
+ if (connection->state >= LM_CONNECTION_STATE_OPENING) {
+ connection_do_close (connection);
+ }
+
g_free (connection->server);
g_free (connection->jid);
g_free (connection->effective_jid);
g_free (connection->stream_id);
g_free (connection->resource);
- if (connection->sasl) {
+ if (connection->sasl) {
lm_sasl_free (connection->sasl);
}
@@ -218,13 +226,9 @@
g_slist_free (connection->handlers[i]);
}
+ g_hash_table_destroy (connection->id_handlers);
- g_hash_table_destroy (connection->id_handlers);
- if (connection->state >= LM_CONNECTION_STATE_OPENING) {
- connection_do_close (connection);
- }
-
- if (connection->open_cb) {
+ if (connection->open_cb) {
_lm_utils_free_callback (connection->open_cb);
}
@@ -2030,11 +2034,11 @@
g_return_if_fail (handler != NULL);
g_return_if_fail (type != LM_MESSAGE_TYPE_UNKNOWN);
- for (l = connection->handlers[type]; l; l = l->next) {
- HandlerData *hd = (HandlerData *) l->data;
-
+ for (l = connection->handlers[type]; l; l = l->next) {
+ HandlerData *hd = (HandlerData *) l->data;
+
if (handler == hd->handler) {
- connection->handlers[type] = g_slist_remove_link (connection->handlers[type], l);
+ connection->handlers[type] = g_slist_remove_link (connection->handlers[type], l);
g_slist_free (l);
lm_message_handler_unref (hd->handler);
g_free (hd);
@@ -2140,7 +2144,7 @@
g_return_val_if_fail (connection != NULL, NULL);
connection->ref_count++;
-
+
return connection;
}
@@ -2157,8 +2161,8 @@
g_return_if_fail (connection != NULL);
connection->ref_count--;
-
+
if (connection->ref_count == 0) {
- connection_free (connection);
+ connection_free (connection);
}
}
--- a/loudmouth/lm-sasl.c Wed Nov 19 10:16:40 2008 +0100
+++ b/loudmouth/lm-sasl.c Sun Nov 30 09:27:21 2008 +0100
@@ -807,27 +807,27 @@
g_free (sasl->server);
if (sasl->features_cb) {
- lm_connection_unregister_message_handler (sasl->connection,
- sasl->features_cb,
- LM_MESSAGE_TYPE_STREAM_FEATURES);
+ lm_connection_unregister_message_handler (sasl->connection,
+ sasl->features_cb,
+ LM_MESSAGE_TYPE_STREAM_FEATURES);
}
if (sasl->challenge_cb) {
lm_connection_unregister_message_handler (sasl->connection,
- sasl->challenge_cb,
- LM_MESSAGE_TYPE_CHALLENGE);
+ sasl->challenge_cb,
+ LM_MESSAGE_TYPE_CHALLENGE);
}
if (sasl->success_cb) {
lm_connection_unregister_message_handler (sasl->connection,
- sasl->success_cb,
- LM_MESSAGE_TYPE_SUCCESS);
+ sasl->success_cb,
+ LM_MESSAGE_TYPE_SUCCESS);
}
if (sasl->failure_cb) {
lm_connection_unregister_message_handler (sasl->connection,
- sasl->failure_cb,
- LM_MESSAGE_TYPE_FAILURE);
+ sasl->failure_cb,
+ LM_MESSAGE_TYPE_FAILURE);
}
g_free (sasl);