From 2dbf54237732ede557b3625a6d34819416d71ca8 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthony.minessale@gmail.com>
Date: Tue, 10 Mar 2009 20:56:38 +0000
Subject: [PATCH] fix unclean shutdown

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@693 a93c3328-9c30-0410-af19-c9cd2b2d52af
---
 libs/freetdm/src/include/openzap.h            |  1 +
 libs/freetdm/src/include/zap_types.h          |  5 +-
 .../src/ozmod/ozmod_libpri/lpwrap_pri.c       | 24 +++--
 .../src/ozmod/ozmod_libpri/lpwrap_pri.h       | 10 +-
 .../src/ozmod/ozmod_libpri/ozmod_libpri.c     | 96 ++++++++++++-------
 libs/freetdm/src/zap_io.c                     | 15 ++-
 6 files changed, 98 insertions(+), 53 deletions(-)

diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h
index ed4308be07..88fd998b43 100644
--- a/libs/freetdm/src/include/openzap.h
+++ b/libs/freetdm/src/include/openzap.h
@@ -543,6 +543,7 @@ struct zap_span {
 	zio_channel_outgoing_call_t outgoing_call;
 	zio_channel_request_t channel_request;
 	zap_span_start_t start;
+	zap_span_stop_t stop;
 	void *mod_data;
 	char *type;
 	char *dtmf_hangup;
diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h
index 09ea5fa4ac..e5218ca4b8 100644
--- a/libs/freetdm/src/include/zap_types.h
+++ b/libs/freetdm/src/include/zap_types.h
@@ -282,7 +282,9 @@ typedef enum {
 	ZAP_SPAN_CONFIGURED = (1 << 0),
 	ZAP_SPAN_READY = (1 << 1),
 	ZAP_SPAN_STATE_CHANGE = (1 << 2),
-	ZAP_SPAN_SUSPENDED = (1 << 3)
+	ZAP_SPAN_SUSPENDED = (1 << 3),
+	ZAP_SPAN_IN_THREAD = (1 << 4),
+	ZAP_SPAN_STOP_THREAD = (1 << 5)
 } zap_span_flag_t;
 
 typedef enum {
@@ -529,6 +531,7 @@ typedef struct value zap_hash_val_t;
 typedef struct zap_bitstream zap_bitstream_t;
 typedef struct zap_fsk_modulator zap_fsk_modulator_t;
 typedef zap_status_t (*zap_span_start_t)(zap_span_t *span);
+typedef zap_status_t (*zap_span_stop_t)(zap_span_t *span);
 
 typedef enum {
 	ZAP_CAUSE_NONE = 0,
diff --git a/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.c
index 1220a93a77..ce38d8ea76 100644
--- a/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.c
+++ b/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.c
@@ -98,7 +98,8 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
 	{16, LPWRAP_PRI_EVENT_NOTIFY, "NOTIFY"},
 	{17, LPWRAP_PRI_EVENT_PROGRESS, "PROGRESS"},
 	{18, LPWRAP_PRI_EVENT_KEYPAD_DIGIT, "KEYPAD_DIGIT"},
-	{19, LPWRAP_PRI_EVENT_IO_FAIL, "IO_FAIL"}
+	{19, LPWRAP_PRI_EVENT_IO_FAIL, "IO_FAIL"},
+	{20, LPWRAP_PRI_EVENT_TIME_CHECK, "TIME_CHECK"}
 };
 
 #define LINE "--------------------------------------------------------------------------------"
@@ -114,8 +115,8 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
 	zap_size_t len = buflen;
 	int res;
 
-	if (zap_channel_read(spri->zdchan, buf, &len) != ZAP_SUCCESS) {
-		zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span, spri->zdchan->last_error);
+	if (zap_channel_read(spri->dchan, buf, &len) != ZAP_SUCCESS) {
+		zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
 		zap_clear_flag(spri, LPWRAP_PRI_READY);
 		return -1;
 	}
@@ -134,8 +135,8 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
 	struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
 	zap_size_t len = buflen -2;
 
-	if (zap_channel_write(spri->zdchan, buf, buflen, &len) != ZAP_SUCCESS) {
-		zap_log(ZAP_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span, spri->zdchan->last_error);
+	if (zap_channel_write(spri->dchan, buf, buflen, &len) != ZAP_SUCCESS) {
+		zap_log(ZAP_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
 		zap_clear_flag(spri, LPWRAP_PRI_READY);
         return -1;
 	}
@@ -146,15 +147,15 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
 	return (int) buflen;
 }
 
-int lpwrap_init_pri(struct lpwrap_pri *spri, int span, zap_channel_t *dchan, int swtype, int node, int debug)
+int lpwrap_init_pri(struct lpwrap_pri *spri, zap_span_t *span, zap_channel_t *dchan, int swtype, int node, int debug)
 {
 	int ret = -1;
 
 	memset(spri, 0, sizeof(struct lpwrap_pri));
 	
-	spri->zdchan = dchan;
+	spri->dchan = dchan;
 
-	if ((spri->pri = pri_new_cb(spri->zdchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))){
+	if ((spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))){
 		spri->span = span;
 		pri_set_debug(spri->pri, debug);
 		ret = 0;
@@ -203,6 +204,13 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
 	event = NULL;
 
 	if (!sel) {
+		if ((handler = spri->eventmap[LPWRAP_PRI_EVENT_TIME_CHECK] ? 
+			 spri->eventmap[LPWRAP_PRI_EVENT_TIME_CHECK] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
+			if (handler(spri, LPWRAP_PRI_EVENT_TIME_CHECK, NULL) < 0) {
+				return -1;
+			}
+		}
+
 		if ((next = pri_schedule_next(spri->pri))) {
 			gettimeofday(&now, NULL);
 			if (now.tv_sec >= next->tv_sec && (now.tv_usec >= next->tv_usec || next->tv_usec <= 100000)) {
diff --git a/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.h b/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.h
index 8ed6ab016f..5137ee4190 100644
--- a/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.h
+++ b/libs/freetdm/src/ozmod/ozmod_libpri/lpwrap_pri.h
@@ -59,7 +59,8 @@ typedef enum {
 	LPWRAP_PRI_EVENT_NOTIFY = PRI_EVENT_NOTIFY,
 	LPWRAP_PRI_EVENT_PROGRESS = PRI_EVENT_PROGRESS,
 	LPWRAP_PRI_EVENT_KEYPAD_DIGIT = PRI_EVENT_KEYPAD_DIGIT,
-	LPWRAP_PRI_EVENT_IO_FAIL = 19
+	LPWRAP_PRI_EVENT_IO_FAIL = 19,
+	LPWRAP_PRI_EVENT_TIME_CHECK = 20
 } lpwrap_pri_event_t;
 
 typedef enum {
@@ -92,13 +93,12 @@ typedef int (*loop_handler)(struct lpwrap_pri *);
 
 struct lpwrap_pri {
 	struct pri *pri;
-	int span;
-	int dchan;
+	zap_span_t *span;
+	zap_channel_t *dchan;
 	unsigned int flags;
 	void *private_info;
 	event_handler eventmap[MAX_EVENT+1];
 	loop_handler on_loop;
-	zap_channel_t *zdchan;
 };
 
 typedef struct lpwrap_pri lpwrap_pri_t;
@@ -115,7 +115,7 @@ struct lpwrap_pri_event_list {
 
 const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id);
 int lpwrap_one_loop(struct lpwrap_pri *spri);
-int lpwrap_init_pri(struct lpwrap_pri *spri, int span, zap_channel_t *dchan, int swtype, int node, int debug);
+int lpwrap_init_pri(struct lpwrap_pri *spri, zap_span_t *span, zap_channel_t *dchan, int swtype, int node, int debug);
 int lpwrap_run_pri(struct lpwrap_pri *spri);
 
 #endif
diff --git a/libs/freetdm/src/ozmod/ozmod_libpri/ozmod_libpri.c b/libs/freetdm/src/ozmod/ozmod_libpri/ozmod_libpri.c
index a3f4a6a205..494751a7ab 100644
--- a/libs/freetdm/src/ozmod/ozmod_libpri/ozmod_libpri.c
+++ b/libs/freetdm/src/ozmod/ozmod_libpri/ozmod_libpri.c
@@ -99,7 +99,7 @@ static int parse_debug(const char *in)
 	if (strstr(in, "q931_dump")) {
 		flags |= PRI_DEBUG_Q931_DUMP;
 	}
-
+	
 	if (strstr(in, "q931_state")) {
 		flags |= PRI_DEBUG_Q931_STATE;
 	}
@@ -501,7 +501,7 @@ static __inline__ void check_state(zap_span_t *span)
 
 
 
-static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 
 	zap_log(ZAP_LOG_DEBUG, "number is: %s\n", pevent->ring.callednum);
@@ -512,7 +512,7 @@ static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
 	return 0;
 }
 
-static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 	zap_span_t *span = spri->private_info;
 	zap_channel_t *zchan = NULL;
@@ -521,20 +521,20 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
 	
 	if (zchan) {
 		call = (q931_call *) zchan->call_data;
-		zap_log(ZAP_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span, pevent->hangup.channel);
+		zap_log(ZAP_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel);
 		zchan->caller_data.hangup_cause = pevent->hangup.cause;
 		pri_release(spri->pri, call, 0);
 		pri_destroycall(spri->pri, call);
 		zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING);
 	} else {
-		zap_log(ZAP_LOG_DEBUG, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span,
+		zap_log(ZAP_LOG_DEBUG, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
 				pevent->hangup.channel, zchan->chan_id);
 	}
 
 	return 0;
 }
 
-static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 	zap_span_t *span = spri->private_info;
 	zap_channel_t *zchan = NULL;
@@ -542,10 +542,10 @@ static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
 	zchan = span->channels[pevent->answer.channel];
 	
 	if (zchan) {
-		zap_log(ZAP_LOG_DEBUG, "-- Answer on channel %d:%d\n", spri->span, pevent->answer.channel);
+		zap_log(ZAP_LOG_DEBUG, "-- Answer on channel %d:%d\n", spri->span->span_id, pevent->answer.channel);
 		zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
 	} else {
-		zap_log(ZAP_LOG_DEBUG, "-- Answer on channel %d:%d %s but it's not in use?\n", spri->span, pevent->answer.channel, zchan->chan_id);
+		zap_log(ZAP_LOG_DEBUG, "-- Answer on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->answer.channel, zchan->chan_id);
 				
 	}
 
@@ -553,7 +553,7 @@ static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
 }
 
 
-static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 	zap_span_t *span = spri->private_info;
 	zap_channel_t *zchan = NULL;
@@ -561,10 +561,10 @@ static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
 	zchan = span->channels[pevent->proceeding.channel];
 	
 	if (zchan) {
-		zap_log(ZAP_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", spri->span, pevent->proceeding.channel);
+		zap_log(ZAP_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", spri->span->span_id, pevent->proceeding.channel);
 		zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
 	} else {
-		zap_log(ZAP_LOG_DEBUG, "-- Proceeding on channel %d:%d %s but it's not in use?\n", spri->span,
+		zap_log(ZAP_LOG_DEBUG, "-- Proceeding on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
 						  pevent->proceeding.channel, zchan->chan_id);
 	}
 
@@ -572,7 +572,7 @@ static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
 }
 
 
-static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 	zap_span_t *span = spri->private_info;
 	zap_channel_t *zchan = NULL;
@@ -580,10 +580,10 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
 	zchan = span->channels[pevent->ringing.channel];
 	
 	if (zchan) {
-		zap_log(ZAP_LOG_DEBUG, "-- Ringing on channel %d:%d\n", spri->span, pevent->ringing.channel);
+		zap_log(ZAP_LOG_DEBUG, "-- Ringing on channel %d:%d\n", spri->span->span_id, pevent->ringing.channel);
 		zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_PROGRESS);
 	} else {
-		zap_log(ZAP_LOG_DEBUG, "-- Ringing on channel %d:%d %s but it's not in use?\n", spri->span,
+		zap_log(ZAP_LOG_DEBUG, "-- Ringing on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
 						  pevent->ringing.channel, zchan->chan_id);
 	}
 
@@ -601,19 +601,19 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
 	
 	zchan = span->channels[pevent->ring.channel];
 	if (!zchan || zchan->state != ZAP_CHANNEL_STATE_DOWN || zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) {
-		zap_log(ZAP_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", spri->span, pevent->ring.channel);
+		zap_log(ZAP_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
 		ret = 0;
 		goto done;
 	}
 
 	if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
-		zap_log(ZAP_LOG_WARNING, "--Failure opening channel %d:%d (ignored)\n", spri->span, pevent->ring.channel);
+		zap_log(ZAP_LOG_WARNING, "--Failure opening channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
 		ret = 0;
 		goto done;
 	}
 	
 
-	zap_log(ZAP_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", spri->span, pevent->ring.channel,
+	zap_log(ZAP_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", spri->span->span_id, pevent->ring.channel,
 					  pevent->ring.callingnum, pevent->ring.callednum);
 	
 	memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
@@ -651,12 +651,12 @@ static int check_flags(lpwrap_pri_t *spri)
 	return 0;
 }
 
-static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 	zap_span_t *span = spri->private_info;
 	zap_channel_t *zchan;
 
-	zap_log(ZAP_LOG_NOTICE, "-- Restarting %d:%d\n", spri->span, pevent->restart.channel);
+	zap_log(ZAP_LOG_NOTICE, "-- Restarting %d:%d\n", spri->span->span_id, pevent->restart.channel);
 
 	zchan = span->channels[pevent->restart.channel];
 
@@ -673,45 +673,55 @@ static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
 	return 0;
 }
 
-static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 	
 	if (!zap_test_flag(spri, LPWRAP_PRI_READY)) {
-		zap_log(ZAP_LOG_INFO, "Span %d D-Chan UP!\n", spri->span);
+		zap_log(ZAP_LOG_INFO, "Span %d D-Chan UP!\n", spri->span->span_id);
 		zap_set_flag(spri, LPWRAP_PRI_READY);
 	}
 
 	return 0;
 }
 
-static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 
 	if (zap_test_flag(spri, LPWRAP_PRI_READY)) {
-		zap_log(ZAP_LOG_INFO, "Span %d D-Chan DOWN!\n", spri->span);
+		zap_log(ZAP_LOG_INFO, "Span %d D-Chan DOWN!\n", spri->span->span_id);
 		zap_clear_flag(spri, LPWRAP_PRI_READY);
 	}
 
 	return 0;
 }
 
-static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 
-	zap_log(ZAP_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span, event_type, lpwrap_pri_event_str(event_type));
+	zap_log(ZAP_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
 	return 0;
 }
 
 
 
-static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event * pevent)
+static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
 
-	zap_log(ZAP_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span, event_type, lpwrap_pri_event_str(event_type));
+	zap_log(ZAP_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
 	return 0;
 }
 
 
+static int on_time_check(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
+{
+
+	if (!zap_running() || zap_test_flag(spri->span, ZAP_SPAN_STOP_THREAD)) {
+		return -1;
+	}
+
+	return 0;
+}
+
 
 static void *zap_libpri_run(zap_thread_t *me, void *obj)
 {
@@ -719,7 +729,9 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
 	zap_libpri_data_t *isdn_data = span->signal_data;
 	int x, i;
 	
-	while(zap_running()) {
+	zap_set_flag(span, ZAP_SPAN_IN_THREAD);
+	
+	while(zap_running() && !zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
 		x = 0;
 
 		for(i = 1; i <= span->chan_count; i++) {
@@ -734,12 +746,12 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
 		}
 
 		
-		if (x && lpwrap_init_pri(&isdn_data->spri,
-							span->span_id,  // span
-							isdn_data->dchan, // dchan
-							isdn_data->pswitch,
-							isdn_data->node,
-							isdn_data->debug) < 0) {
+		if (!x || lpwrap_init_pri(&isdn_data->spri,
+								  span,  // span
+								  isdn_data->dchan, // dchan
+								  isdn_data->pswitch,
+								  isdn_data->node,
+								  isdn_data->debug) < 0) {
 			snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!");
 		} else {
 
@@ -756,6 +768,7 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
 			LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info);
 			LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);
 			LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_IO_FAIL, on_io_fail);
+			LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_TIME_CHECK, on_time_check);
 
 
 			isdn_data->spri.on_loop = check_flags;
@@ -765,14 +778,28 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
 			zap_channel_close(&isdn_data->dchan);
 		}
 		
+		if (!zap_running() || zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
+			break;
+		}
+
 		zap_log(ZAP_LOG_CRIT, "PRI down on span %d\n", isdn_data->spri.span);
 		zap_sleep(5000);
 	}
 
+	zap_clear_flag(span, ZAP_SPAN_IN_THREAD);
 	
 	return NULL;
 }
 
+static zap_status_t zap_libpri_stop(zap_span_t *span)
+{
+	zap_set_flag(span, ZAP_SPAN_STOP_THREAD);
+	while(zap_test_flag(span, ZAP_SPAN_IN_THREAD)) {
+		zap_sleep(100);
+	}
+	return ZAP_SUCCESS;
+}
+
 static zap_status_t zap_libpri_start(zap_span_t *span)
 {
 	zap_status_t ret;
@@ -934,6 +961,7 @@ static ZIO_SIG_CONFIGURE_FUNCTION(zap_libpri_configure_span)
 	
 
 	span->start = zap_libpri_start;
+	span->stop = zap_libpri_stop;
 	isdn_data->sig_cb = sig_cb;
 	//isdn_data->dchans[0] = dchans[0];
 	//isdn_data->dchans[1] = dchans[1];
diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c
index e10928a427..8b201853e5 100644
--- a/libs/freetdm/src/zap_io.c
+++ b/libs/freetdm/src/zap_io.c
@@ -219,11 +219,16 @@ 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) && 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);
+	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;