diff freeDiameter/cnxctx.c @ 155:30a7252cbb55

Cleanup connection cleanup sequence
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 19 Jan 2010 11:41:01 +0900
parents abd3c441780b
children e2dc300819b3
line wrap: on
line diff
--- a/freeDiameter/cnxctx.c	Tue Dec 22 15:53:13 2009 +0900
+++ b/freeDiameter/cnxctx.c	Tue Jan 19 11:41:01 2010 +0900
@@ -561,7 +561,9 @@
 	TRACE_DEBUG(FULL, "Thread terminated");	
 	return NULL;
 error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
+	if (!conn->cc_closing) {
+		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
+	}
 	goto out;
 }
 
@@ -602,7 +604,9 @@
 	TRACE_DEBUG(FULL, "Thread terminated");	
 	return NULL;
 error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
+	if (!conn->cc_closing) {
+		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
+	}
 	goto out;
 }
 #endif /* DISABLE_SCTP */
@@ -712,7 +716,9 @@
 	
 	CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
 error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
+	if (!conn->cc_closing) {
+		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
+	}
 	TRACE_DEBUG(FULL, "Thread terminated");	
 	return NULL;
 }
@@ -1132,7 +1138,7 @@
 	return 0;
 }
 
-/* Wrapper around gnutls_record_recv to handle some error codes */
+/* Wrapper around gnutls_record_send to handle some error codes */
 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
 {
 	ssize_t ret;
@@ -1245,35 +1251,51 @@
 	
 	CHECK_PARAMS_DO(conn, return);
 	
-	/* Avoid sending further events to the alt fifo */
-	conn->cc_alt = NULL;
-
-	/* In case of TLS, stop receiver thread, then close properly the gnutls session */
-	if ((conn->cc_tls) && (conn->cc_sctp_para.pairs > 1)) {
+	conn->cc_closing = 1;
+	
+	/* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */
+	if (conn->cc_tls) {
 #ifndef DISABLE_SCTP
-		/* Multi-stream TLS: Stop all decipher threads, but not the demux thread */
-		fd_sctps_stopthreads(conn);
+		if (conn->cc_sctp_para.pairs > 1) {
+			/* Master session */
+			CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), /* Continue */ );
+			
+			/* and other stream pairs */
+			fd_sctps_bye(conn);
+			
+			/* Now wait for all decipher threads to terminate */
+			fd_sctps_waitthreadsterm(conn);
+			
+			/* Deinit gnutls resources */
+			fd_sctps_gnutls_deinit_others(conn);
+			gnutls_deinit(conn->cc_tls_para.session);
+			
+			/* Destroy the wrapper (also stops the demux thread) */
+			fd_sctps_destroy(conn);
+
+		} else {
 #endif /* DISABLE_SCTP */
-	} else {
-		/* Stop the decoding thread */
-		CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
+		/* We are not using the sctps wrapper layer */
+			/* Master session */
+			CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), /* Continue */ );
+		
+			/* In this case, just wait for thread rcvthr_tls_single to terminate */
+			if (conn->cc_rcvthr != (pthread_t)NULL) {
+				CHECK_POSIX_DO(  pthread_join(conn->cc_rcvthr, NULL), /* continue */  );
+				conn->cc_rcvthr = (pthread_t)NULL;
+			}
+			
+			/* Free the resources of the TLS session */
+			gnutls_deinit(conn->cc_tls_para.session);
+		
+#ifndef DISABLE_SCTP
+		}
+#endif /* DISABLE_SCTP */
 	}
 	
-	/* Terminate properly the TLS session(s) */
-	if (conn->cc_tls) {
-		/* Master session */
-		CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), /* Continue */ );
-		gnutls_deinit(conn->cc_tls_para.session);
+	/* Terminate the thread in case it is not done yet */
+	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
 		
-#ifndef DISABLE_SCTP
-		if (conn->cc_sctp_para.pairs > 1) {
-			/* Multi-stream TLS: destroy the wrapper and stop the demux thread */
-			fd_sctps_destroy(conn);
-		}
-#endif /* DISABLE_SCTP */
-		
-	}
-	
 	/* Shut the connection down */
 	if (conn->cc_socket > 0) {
 		shutdown(conn->cc_socket, SHUT_RDWR);
"Welcome to our mercurial repository"