[asterisk-commits] russell: branch 1.4 r55758 - /branches/1.4/apps/app_meetme.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue Feb 20 18:03:26 MST 2007


Author: russell
Date: Tue Feb 20 19:03:25 2007
New Revision: 55758

URL: http://svn.digium.com/view/asterisk?view=rev&rev=55758
Log:
Improve the reference counting to fix bugs where people report seeing
conferences listed that have no members.
(issue #9073)

Modified:
    branches/1.4/apps/app_meetme.c

Modified: branches/1.4/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/apps/app_meetme.c?view=diff&rev=55758&r1=55757&r2=55758
==============================================================================
--- branches/1.4/apps/app_meetme.c (original)
+++ branches/1.4/apps/app_meetme.c Tue Feb 20 19:03:25 2007
@@ -641,7 +641,7 @@
 static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount)
 {
 	struct ast_conference *cnf;
-	struct zt_confinfo ztc;
+	struct zt_confinfo ztc = { 0, };
 
 	AST_LIST_LOCK(&confs);
 
@@ -662,8 +662,6 @@
 	ast_copy_string(cnf->confno, confno, sizeof(cnf->confno));
 	ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
 	ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
-	cnf->refcount = 0;
-	cnf->markedusers = 0;
 	cnf->chan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
 	if (cnf->chan) {
 		ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR);
@@ -679,9 +677,8 @@
 			goto cnfout;
 		}
 	}
-	memset(&ztc, 0, sizeof(ztc));
+	
 	/* Setup a new zap conference */
-	ztc.chan = 0;
 	ztc.confno = -1;
 	ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON;
 	if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) {
@@ -716,7 +713,7 @@
 	
 cnfout:
 	if (cnf)
-		cnf->refcount += refcount;
+		ast_atomic_fetchadd_int(&cnf->refcount, refcount);
 
 	AST_LIST_UNLOCK(&confs);
 
@@ -1063,6 +1060,7 @@
 		conf->recording = MEETME_RECORD_TERMINATE;
 		AST_LIST_UNLOCK(&confs);
 		while (1) {
+			usleep(1);
 			AST_LIST_LOCK(&confs);
 			if (conf->recording == MEETME_RECORD_OFF)
 				break;
@@ -1148,6 +1146,22 @@
 	ast_cond_signal(&sla.cond);
 	ast_mutex_unlock(&sla.lock);
 }
+
+/* Decrement reference counts, as incremented by find_conf() */
+static int dispose_conf(struct ast_conference *conf)
+{
+	int res = 0;
+
+	AST_LIST_LOCK(&confs);
+	if (ast_atomic_dec_and_test(&conf->refcount)) {
+		conf_free(conf);
+		res = 1;
+	}
+	AST_LIST_UNLOCK(&confs);
+
+	return res;
+}
+
 
 static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags, char *optargs[])
 {
@@ -1191,15 +1205,8 @@
 	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
 	char *buf = __buf + AST_FRIENDLY_OFFSET;
 
-	if (!(user = ast_calloc(1, sizeof(*user)))) {
-		AST_LIST_LOCK(&confs);
-		conf->refcount--;
-		if (!conf->refcount){
-			conf_free(conf);
-		}
-		AST_LIST_UNLOCK(&confs);
+	if (!(user = ast_calloc(1, sizeof(*user))))
 		return ret;
-	}
 
 	/* Possible timeout waiting for marked user */
 	if ((confflags & CONFFLAG_WAITMARKED) &&
@@ -2059,7 +2066,6 @@
 		}
 
 		conf->users--;
-		conf->refcount--;
 		/* Update table */
 		snprintf(members, sizeof(members), "%d", conf->users);
 		ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL);
@@ -2071,12 +2077,7 @@
 		/* Change any states */
 		if (!conf->users)
 			ast_device_state_changed("meetme:%s", conf->confno);
-
-		if (AST_LIST_EMPTY(&conf->userlist)) {
-			/* close this one when no more users and no references*/
-			if (!conf->refcount)
-				conf_free(conf);
-		}
+		
 		/* Return the number of seconds the user was in the conf */
 		snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime));
 		pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs);
@@ -2265,11 +2266,13 @@
 
 	AST_STANDARD_APP_ARGS(args, localdata);
 	
-	conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 0, NULL);
-
-	if (conf)
+	conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL);
+
+	if (conf) {
 		count = conf->users;
-	else
+		dispose_conf(conf);
+		conf = NULL;
+	} else
 		count = 0;
 
 	if (!ast_strlen_zero(args.varname)){
@@ -2294,7 +2297,7 @@
 	char confno[MAX_CONFNUM] = "";
 	int allowretry = 0;
 	int retrycnt = 0;
-	struct ast_conference *cnf;
+	struct ast_conference *cnf = NULL;
 	struct ast_flags confflags = {0};
 	int dynamic = 0;
 	int empty = 0, empty_no_pin = 0;
@@ -2505,15 +2508,8 @@
 									ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n");
 									break;
 								}
-								if (res < 0) {
-									AST_LIST_LOCK(&confs);
-									cnf->refcount--;
-									if (!cnf->refcount){
-										conf_free(cnf);
-									}
-									AST_LIST_UNLOCK(&confs);
+								if (res < 0)
 									break;
-								}
 								pin[0] = res;
 								pin[1] = '\0';
 								res = -1;
@@ -2525,12 +2521,6 @@
 							res = -1;
 							allowretry = 0;
 							/* see if we need to get rid of the conference */
-							AST_LIST_LOCK(&confs);
-							cnf->refcount--;
-							if (!cnf->refcount) {
-								conf_free(cnf);
-							}
-							AST_LIST_UNLOCK(&confs);
 							break;
 						}
 
@@ -2547,9 +2537,14 @@
 					res = conf_run(chan, cnf, confflags.flags, optargs);
 				}
 			}
+			dispose_conf(cnf);
+			cnf = NULL;
 		}
 	} while (allowretry);
-	
+
+	if (cnf)
+		dispose_conf(cnf);
+
 	ast_module_user_remove(u);
 	
 	return res;
@@ -2612,6 +2607,8 @@
 		ast_module_user_remove(u);
 		return 0;
 	}
+
+	ast_atomic_fetchadd_int(&cnf->refcount, 1);
 
 	if (args.user)
 		user = find_user(cnf, args.user);
@@ -2716,6 +2713,8 @@
 
 	AST_LIST_UNLOCK(&confs);
 
+	dispose_conf(cnf);
+
 	ast_module_user_remove(u);
 	
 	return 0;
@@ -3009,8 +3008,11 @@
 		CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION);
 	ast_answer(trunk_ref->chan);
 	conf = build_conf(conf_name, "", "", 0, 0, 1);
-	if (conf)
+	if (conf) {
 		conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL);
+		dispose_conf(conf);
+		conf = NULL;
+	}
 	trunk_ref->chan = NULL;
 	if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations)) {
 		strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1);
@@ -3325,8 +3327,11 @@
 	ast_cond_signal(args->cond);
 	ast_mutex_unlock(args->cond_lock);
 
-	if (conf)
+	if (conf) {
 		conf_run(trunk->chan, conf, conf_flags.flags, NULL);
+		dispose_conf(conf);
+		conf = NULL;
+	}
 
 	trunk->chan = NULL;
 
@@ -3431,8 +3436,11 @@
 	trunk_ref->chan = chan;
 	ast_answer(chan);
 	conf = build_conf(conf_name, "", "", 0, 0, 1);
-	if (conf)
+	if (conf) {
 		conf_run(chan, conf, conf_flags.flags, NULL);
+		dispose_conf(conf);
+		conf = NULL;
+	}
 	trunk_ref->chan = NULL;
 	res = ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, -1);
 	if (res == 1) {	
@@ -3508,6 +3516,8 @@
 		CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF);
 	ast_indicate(chan, AST_CONTROL_RINGING);
 	conf_run(chan, conf, conf_flags.flags, NULL);
+	dispose_conf(conf);
+	conf = NULL;
 	trunk->chan = NULL;
 
 	pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS");



More information about the asterisk-commits mailing list