From 15c93b5c0d02b99258a832b864feab0cd5375cc8 Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Wed, 9 Dec 2009 18:51:55 +0000
Subject: [PATCH] Changes for segfaults on shutdown and cpu usage

git-svn-id: http://svn.openzap.org/svn/openzap/branches/sangoma_boost@932 a93c3328-9c30-0410-af19-c9cd2b2d52af
---
 .../ozmod_sangoma_boost/ozmod_sangoma_boost.c | 14 ++-
 .../src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c   | 13 ++-
 libs/freetdm/src/zap_io.c                     | 93 +++++++++++--------
 3 files changed, 74 insertions(+), 46 deletions(-)

diff --git a/libs/freetdm/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c b/libs/freetdm/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c
index 8706a1b401..a1b289a06b 100644
--- a/libs/freetdm/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c
+++ b/libs/freetdm/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c
@@ -1413,10 +1413,10 @@ static sangomabc_event_t *zap_boost_read_event(zap_span_t *span)
  */
 static void *zap_sangoma_boost_run(zap_thread_t *me, void *obj)
 {
-    zap_span_t *span = (zap_span_t *) obj;
+	zap_span_t *span = (zap_span_t *) obj;
 	sangomabc_connection_t *mcon, *pcon;
 	uint32_t ms = 10;
-    zap_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
+  zap_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
 
 	mcon = &sangoma_boost_data->mcon;
 	pcon = &sangoma_boost_data->pcon;	
@@ -1466,7 +1466,7 @@ static void *zap_sangoma_boost_run(zap_thread_t *me, void *obj)
 			break;
 		}
 
-		if ((activity = zap_boost_wait_event(span, ms)) < 0) {
+		if ((activity = zap_boost_wait_event(span, -1)) < 0) {
 			zap_log(ZAP_LOG_ERROR, "zap_boost_wait_event failed\n");
 			goto error;
 		}
@@ -1568,13 +1568,21 @@ static zap_status_t zap_sangoma_boost_start(zap_span_t *span)
 
 static zap_status_t zap_sangoma_boost_stop(zap_span_t *span)
 {
+	int cnt = 10;
 	zap_status_t status = ZAP_SUCCESS;
 	zap_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
 	if (sangoma_boost_data->sigmod) {
+
 		/* FIXME: we should make sure the span thread is stopped (use pthread_kill or openzap thread kill function) */
 		/* I think stopping the span before destroying the queue makes sense
 		   otherwise may be boost events would still arrive when the queue is already destroyed! */
 		status = sangoma_boost_data->sigmod->stop_span(span);
+
+		zap_queue_enqueue(sangoma_boost_data->boost_queue, NULL);
+		while(zap_test_flag(sangoma_boost_data, ZAP_SANGOMA_BOOST_RUNNING) && cnt-- > 0) {
+			zap_log(ZAP_LOG_DEBUG, "Waiting for boost thread\n");
+			zap_sleep(500);
+		}
 		zap_queue_destroy(&sangoma_boost_data->boost_queue);
 		return status;
 	}
diff --git a/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
index 74368d5354..a6f436ffc5 100644
--- a/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
+++ b/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
@@ -245,7 +245,11 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
 			wanpipe_tdm_api_t tdm_api;
 			memset(&tdm_api, 0, sizeof(tdm_api));
 #ifdef LIBSANGOMA_VERSION
-			sangstatus = sangoma_wait_obj_create(&sangoma_wait_obj, sockfd, SANGOMA_DEVICE_WAIT_OBJ);
+			/* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call 
+			 * sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on zap shutdown)
+			 * this adds an extra pair of file descriptors to the waitable object
+			 * */
+			sangstatus = sangoma_wait_obj_create(&sangoma_wait_obj, sockfd, SANGOMA_DEVICE_WAIT_OBJ_SIG);
 			if (sangstatus != SANG_STATUS_SUCCESS) {
 				zap_log(ZAP_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
 				continue;
@@ -493,6 +497,11 @@ static ZIO_OPEN_FUNCTION(wanpipe_open)
  */
 static ZIO_CLOSE_FUNCTION(wanpipe_close)
 {
+#ifdef LIBSANGOMA_VERSION
+	sangoma_wait_obj_t *waitobj = zchan->mod_data;
+	/* kick any I/O waiters */
+	sangoma_wait_obj_signal(waitobj);
+#endif
 	return ZAP_SUCCESS;
 }
 
@@ -1058,7 +1067,7 @@ static ZIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
 {
 #ifdef LIBSANGOMA_VERSION
 	if (zchan->mod_data) {
-	    sangoma_wait_obj_t *sangoma_wait_obj;
+		sangoma_wait_obj_t *sangoma_wait_obj;
 		sangoma_wait_obj = zchan->mod_data;
 		zchan->mod_data = NULL;
 		sangoma_wait_obj_delete(&sangoma_wait_obj);
diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c
index ba95e94bbf..ced0eb82bb 100644
--- a/libs/freetdm/src/zap_io.c
+++ b/libs/freetdm/src/zap_io.c
@@ -276,26 +276,6 @@ OZ_DECLARE_NONSTD(uint32_t) zap_hash_hashfromstring(void *ky)
     return hash;
 }
 
-
-static zap_status_t zap_span_destroy(zap_span_t *span)
-{
-	zap_status_t status = ZAP_FAIL;
-	
-	if (zap_test_flag(span, ZAP_SPAN_CONFIGURED)) {
-		if (span->stop) {
-			span->stop(span);
-		}
-		if (span->zio && span->zio->span_destroy) {
-			zap_log(ZAP_LOG_INFO, "Destroying span %u type (%s)\n", span->span_id, span->type);
-			status = span->zio->span_destroy(span);
-			zap_safe_free(span->type);
-			zap_safe_free(span->dtmf_hangup);
-		}
-	}
-
-	return status;
-}
-
 static zap_status_t zap_channel_destroy(zap_channel_t *zchan)
 {
 
@@ -342,6 +322,48 @@ static zap_status_t zap_channel_destroy(zap_channel_t *zchan)
 	return ZAP_SUCCESS;
 }
 
+static zap_status_t zap_span_destroy(zap_span_t *span)
+{
+	zap_status_t status = ZAP_SUCCESS;
+	unsigned j;
+
+	zap_mutex_lock(span->mutex);
+
+	/* stop the signaling */
+	if (span->stop) {
+		status = span->stop(span);
+	} 
+
+	/* destroy the channels */
+	zap_clear_flag(span, ZAP_SPAN_CONFIGURED);
+	for(j = 1; j <= span->chan_count && span->channels[j]; j++) {
+		zap_channel_t *cur_chan = span->channels[j];
+		if (cur_chan) {
+			if (zap_test_flag(cur_chan, ZAP_CHANNEL_CONFIGURED)) {
+				zap_channel_destroy(cur_chan);
+			}
+			zap_safe_free(cur_chan);
+			cur_chan = NULL;
+		}
+	}
+
+	/* destroy the I/O for the span */
+	if (span->zio && span->zio->span_destroy) {
+		zap_log(ZAP_LOG_INFO, "Destroying span %u type (%s)\n", span->span_id, span->type);
+		if (span->zio->span_destroy(span) != ZAP_SUCCESS) {
+			status = ZAP_FAIL;
+		}
+		zap_safe_free(span->type);
+		zap_safe_free(span->dtmf_hangup);
+	}
+
+	/* destroy final basic resources of the span data structure */
+	zap_mutex_unlock(span->mutex);
+	zap_mutex_destroy(&span->mutex);
+	zap_safe_free(span->signal_data);
+
+	return status;
+}
 
 OZ_DECLARE(zap_status_t) zap_channel_get_alarms(zap_channel_t *zchan)
 {
@@ -481,7 +503,10 @@ OZ_DECLARE(zap_status_t) zap_span_close_all(void)
 	for (span = globals.spans; span; span = span->next) {
 		if (zap_test_flag(span, ZAP_SPAN_CONFIGURED)) {
 			for(j = 1; j <= span->chan_count && span->channels[j]; j++) {
-				zap_channel_destroy(span->channels[j]);
+				zap_channel_t *toclose = span->channels[j];
+				if (zap_test_flag(toclose, ZAP_CHANNEL_INUSE)) {
+					zap_channel_close(&toclose);
+				}
 				i++;
 			}
 		} 
@@ -1329,11 +1354,17 @@ OZ_DECLARE(zap_status_t) zap_channel_close(zap_channel_t **zchan)
 		return ZAP_FAIL;
 	}
 
+	if (!zap_test_flag(check, ZAP_CHANNEL_INUSE)) {
+		zap_log(ZAP_LOG_WARNING, "Called zap_channel_close but never zap_channel_open in chan %d:%d??\n", check->span_id, check->chan_id);
+		return ZAP_FAIL;
+	}
+
 	if (zap_test_flag(check, ZAP_CHANNEL_CONFIGURED)) {
 		zap_mutex_lock(check->mutex);
 		if (zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
 			status = check->zio->close(check);
 			if (status == ZAP_SUCCESS) {
+				zap_clear_flag(check, ZAP_CHANNEL_INUSE);
 				zap_channel_reset(check);
 				*zchan = NULL;
 			}
@@ -2889,7 +2920,6 @@ OZ_DECLARE(uint32_t) zap_running(void)
 
 OZ_DECLARE(zap_status_t) zap_global_destroy(void)
 {
-	unsigned int j;
 	zap_span_t *sp;
 
 	time_end();
@@ -2905,25 +2935,6 @@ OZ_DECLARE(zap_status_t) zap_global_destroy(void)
 
 		if (cur_span) {
 			if (zap_test_flag(cur_span, ZAP_SPAN_CONFIGURED)) {
-				zap_mutex_lock(cur_span->mutex);
-				zap_clear_flag(cur_span, ZAP_SPAN_CONFIGURED);
-				for(j = 1; j <= cur_span->chan_count && cur_span->channels[j]; j++) {
-					zap_channel_t *cur_chan = cur_span->channels[j];
-					if (cur_chan) {
-						if (zap_test_flag(cur_chan, ZAP_CHANNEL_CONFIGURED)) {
-							zap_channel_destroy(cur_chan);
-						}
-						zap_safe_free(cur_chan);
-						cur_chan = NULL;
-					}
-				}
-				zap_mutex_unlock(cur_span->mutex);
-
-				if (cur_span->mutex) {
-					zap_mutex_destroy(&cur_span->mutex);
-				}
-
-				zap_safe_free(cur_span->signal_data);
 				zap_span_destroy(cur_span);
 			}