[svn-commits] wedhorn: branch wedhorn/skinny-session r390739 - /team/wedhorn/skinny-session...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jun 6 16:00:36 CDT 2013


Author: wedhorn
Date: Thu Jun  6 16:00:34 2013
New Revision: 390739

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390739
Log:
skinny: restructure skinny_session thread to be cancelled externally

Modified:
    team/wedhorn/skinny-session/channels/chan_skinny.c

Modified: team/wedhorn/skinny-session/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/team/wedhorn/skinny-session/channels/chan_skinny.c?view=diff&rev=390739&r1=390738&r2=390739
==============================================================================
--- team/wedhorn/skinny-session/channels/chan_skinny.c (original)
+++ team/wedhorn/skinny-session/channels/chan_skinny.c Thu Jun  6 16:00:34 2013
@@ -2302,34 +2302,9 @@
 	return 1;
 }
 
-static int skinny_unregister(struct skinny_req *req, struct skinnysession *s)
-{
-	struct skinny_device *d;
-	struct skinny_line *l;
-	struct skinny_speeddial *sd;
-
-	d = s->device;
-
-	if (d) {
-		d->session = NULL;
-
-		AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
-			if (sd->stateid > -1)
-				ast_extension_state_del(sd->stateid, NULL);
-		}
-		AST_LIST_TRAVERSE(&d->lines, l, list) {
-			if (l->device == d) {
-				ast_format_cap_remove_all(l->cap);
-				ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
-				l->instance = 0;
-				manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
-				unregister_exten(l);
-				ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
-			}
-		}
-	}
-
-	return -1; /* main loop will destroy the session */
+static void end_session(struct skinnysession *s)
+{
+	pthread_cancel(s->t);
 }
 
 #ifdef AST_DEVMODE
@@ -2395,7 +2370,7 @@
 		ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
 		if (res == -1) {
 			ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
-			skinny_unregister(NULL, s);
+			end_session(s);
 		}
 
 	}
@@ -7322,7 +7297,7 @@
 		break;
 	case UNREGISTER_MESSAGE:
 		SKINNY_DEBUG(DEBUG_PACKET, 3, "Received UNREGISTER_MESSAGE from %s\n", d->name);
-		res = skinny_unregister(req, s);
+		end_session(s);
 		break;
 	case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
 		SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFT_KEY_TEMPLATE_REQ_MESSAGE from %s\n", d->name);
@@ -7349,36 +7324,18 @@
 
 static void destroy_session(struct skinnysession *s)
 {
-	struct skinnysession *cur;
-	AST_LIST_LOCK(&sessions);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, cur, list) {
-		if (cur == s) {
-			AST_LIST_REMOVE_CURRENT(list);
-			if (s->fd > -1) {
-				close(s->fd);
-			}
-
-			if (s->device) {
-				s->device->session = NULL;
-			} else {
- 				ast_atomic_fetchadd_int(&unauth_sessions, -1);
-			}
-
-			ast_mutex_destroy(&s->lock);
-
-			ast_free(s);
-
-			break;
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END
-	AST_LIST_UNLOCK(&sessions);
-}
-
-static void end_session(struct skinnysession *s)
-{
-	s->destroy = 1;
-	pthread_kill(s->t, SIGURG);
+	if (s->fd > -1) {
+		close(s->fd);
+	}
+
+	if (s->device) {
+		s->device->session = NULL;
+	} else {
+		ast_atomic_fetchadd_int(&unauth_sessions, -1);
+	}
+
+	ast_mutex_destroy(&s->lock);
+	ast_free(s);
 }
 
 static int skinny_noauth_cb(const void *data)
@@ -7388,6 +7345,42 @@
 	s->auth_timeout_sched = 0;
 	end_session(s);
 	return 0;
+}
+
+static void skinny_session_cleanup(void *data)
+{
+	struct skinnysession *s = (struct skinnysession *)data;
+	struct skinny_device *d = s->device;
+	struct skinny_line *l;
+	struct skinny_speeddial *sd;
+
+	ast_verb(3, "Ending Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
+
+	if (d) {
+		d->session = NULL;
+
+		AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
+			if (sd->stateid > -1)
+				ast_extension_state_del(sd->stateid, NULL);
+		}
+		AST_LIST_TRAVERSE(&d->lines, l, list) {
+			if (l->device == d) {
+				ast_format_cap_remove_all(l->cap);
+				ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
+				l->instance = 0;
+				manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
+				unregister_exten(l);
+				ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
+			}
+		}
+	}
+	
+	destroy_session(s);
+	
+	AST_LIST_LOCK(&sessions);
+	AST_LIST_REMOVE(&sessions, s, list);
+	AST_LIST_UNLOCK(&sessions);
+	
 }
 
 static void *skinny_session(void *data)
@@ -7407,7 +7400,19 @@
 	}
 
 	ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
-	s->destroy = 0;
+
+	pthread_cleanup_push(skinny_session_cleanup, s);
+	
+	if(time(&s->start) == -1) {
+		ast_log(LOG_ERROR, "error executing time(): %s; continuing without start time\n", strerror(errno));
+	}
+
+	ast_mutex_init(&s->lock);
+	
+	AST_LIST_LOCK(&sessions);
+	AST_LIST_INSERT_HEAD(&sessions, s, list);
+	AST_LIST_UNLOCK(&sessions);
+
 	s->auth_timeout_sched = ast_sched_add(sched, auth_timeout*1000, skinny_noauth_cb, s);
 
 	for (;;) {
@@ -7501,7 +7506,9 @@
 			ast_mutex_unlock(&s->lock);
 			lockstate = 0;
 
+			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
 			res = handle_message(req, s);
+			pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 			if (res < 0) {
 				ast_verb(3, "Ending Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
 				break;
@@ -7521,8 +7528,8 @@
 	if (req) {
 		ast_free(req);
 	}
-	skinny_unregister(NULL, s);
-	destroy_session(s);
+
+	pthread_cleanup_pop(1);
 
 	return 0;
 }
@@ -7563,18 +7570,7 @@
 		}
 
 		memcpy(&s->sin, &sin, sizeof(sin));
-		ast_mutex_init(&s->lock);
 		s->fd = as;
-
-		if(time(&s->start) == -1) {
-			ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
-			destroy_session(s);
-			continue;
-		}
-
-		AST_LIST_LOCK(&sessions);
-		AST_LIST_INSERT_HEAD(&sessions, s, list);
-		AST_LIST_UNLOCK(&sessions);
 
 		if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
 			destroy_session(s);
@@ -8625,6 +8621,7 @@
 	struct skinny_line *l;
 	struct skinny_subchannel *sub;
 	struct ast_context *con;
+	int tempthread;
 
 	ast_rtp_glue_unregister(&skinny_rtp_glue);
 	ast_channel_unregister(&skinny_tech);
@@ -8635,9 +8632,19 @@
 	ast_manager_unregister("SKINNYlines");
 	ast_manager_unregister("SKINNYshowline");
 
+	ast_mutex_lock(&netlock);
+	if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
+		pthread_cancel(accept_t);
+		pthread_kill(accept_t, SIGURG);
+		pthread_join(accept_t, NULL);
+	}
+	accept_t = AST_PTHREADT_STOP;
+	ast_mutex_unlock(&netlock);
+
 	AST_LIST_LOCK(&sessions);
 	/* Destroy all the interfaces and free their memory */
 	while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
+		AST_LIST_UNLOCK(&sessions);
 		d = s->device;
 		AST_LIST_TRAVERSE(&d->lines, l, list){
 			ast_mutex_lock(&l->lock);
@@ -8655,25 +8662,14 @@
 			manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
 			unregister_exten(l);
 		}
-		if (s->fd > -1)
-			close(s->fd);
-		pthread_cancel(s->t);
-		pthread_kill(s->t, SIGURG);
-		pthread_join(s->t, NULL);
-		free(s);
+		tempthread = s->t;
+		pthread_cancel(tempthread);
+		pthread_join(tempthread, NULL);
+		AST_LIST_LOCK(&sessions);
 	}
 	AST_LIST_UNLOCK(&sessions);
 
 	delete_devices();
-
-	ast_mutex_lock(&netlock);
-	if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
-		pthread_cancel(accept_t);
-		pthread_kill(accept_t, SIGURG);
-		pthread_join(accept_t, NULL);
-	}
-	accept_t = AST_PTHREADT_STOP;
-	ast_mutex_unlock(&netlock);
 
 	close(skinnysock);
 	if (sched) {




More information about the svn-commits mailing list