Don't free connection internals before it's closed. [#34]
authorMikael Hallendal <micke@imendio.com>
Sun, 30 Nov 2008 09:27:21 +0100
changeset 572 0a4fa0952ef6
parent 567 0cb53b009e8c
child 574 f84be3f7c7e0
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.
loudmouth/lm-connection.c
loudmouth/lm-sasl.c
--- 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);