[svn-commits] rizzo: branch rizzo/astobj2 r47407 - /team/rizzo/astobj2/channels/chan_sip.c

svn-commits at lists.digium.com svn-commits at lists.digium.com
Thu Nov 9 20:50:53 MST 2006


Author: rizzo
Date: Thu Nov  9 21:50:53 2006
New Revision: 47407

URL: http://svn.digium.com/view/asterisk?view=rev&rev=47407
Log:
rename some pvt pointers to ..._pvt so it is easier to track them.

Note some dubious constructs where the reference is dropped
but the session was not destroyed, possibly causing a memory leak.
The above, unfortunately, applies to trunk/1.4 as well.


Modified:
    team/rizzo/astobj2/channels/chan_sip.c

Modified: team/rizzo/astobj2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/channels/chan_sip.c?view=diff&rev=47407&r1=47406&r2=47407
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Thu Nov  9 21:50:53 2006
@@ -82,7 +82,7 @@
  * the sip_hangup() function
  */
 
-// #define	USE_AO2		// enable to use astobj2
+#define	USE_AO2		// enable to use astobj2
 
 #include "asterisk.h"
 
@@ -862,7 +862,7 @@
 	char replaces_callid[BUFSIZ];			/*!< Replace info: callid */
 	char replaces_callid_totag[BUFSIZ/2];		/*!< Replace info: to-tag */
 	char replaces_callid_fromtag[BUFSIZ/2];		/*!< Replace info: from-tag */
-	struct sip_pvt *refer_call;			/*!< Call we are referring */
+	struct sip_pvt *refer_pvt;			/*!< Call we are referring */
 	int attendedtransfer;				/*!< Attended or blind transfer? */
 	int localtransfer;				/*!< Transfer to local domain? */
 	enum referstatus status;			/*!< REFER status */
@@ -1147,7 +1147,7 @@
 	struct sockaddr_in addr;	/*!<  IP address of peer */
 	
 	/* Qualification */
-	struct sip_pvt *peer_call;		/*!<  Call pointer */
+	struct sip_pvt *peer_pvt;		/*!<  Call pointer */
 	int pokeexpire;			/*!<  When to expire poke (qualify= checking) */
 	int lastms;			/*!<  How long last response took (in ms), or -1 for no response */
 	int maxms;			/*!<  Max ms we will accept for the host to be up, 0 to not monitor */
@@ -1184,7 +1184,7 @@
 	int regattempts;		/*!< Number of attempts (since the last success) */
 	int timeout; 			/*!< sched id of sip_reg_timeout */
 	int refresh;			/*!< How often to refresh */
-	struct sip_pvt *call;		/*!< create a sip_pvt structure for each outbound "registration dialog" in progress */
+	struct sip_pvt *register_pvt;		/*!< create a sip_pvt structure for each outbound "registration dialog" in progress */
 	enum sipregistrystate regstate;	/*!< Registration state (see above) */
 	time_t regtime;		/*!< Last succesful registration time */
 	int callid_valid;		/*!< 0 means we haven't chosen callid for this registry yet. */
@@ -2026,19 +2026,17 @@
 		if (cur == pkt)
 			break;
 	}
-	if (cur) {
+	if (!cur)
+		ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
+	else {
 		if (prev)
 			prev->next = cur->next;
 		else
 			pvt->packets = cur->next;
 		pkt->pvt = pvt_unref(pvt);	/* release the pvt */
-		sip_pvt_unlock(pvt);
 		free(cur);
-		pkt = NULL;
-	} else
-		ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
-	if (pkt)
-		sip_pvt_unlock(pvt);
+	}
+	sip_pvt_unlock(pvt);
 	return 0;
 }
 
@@ -2533,8 +2531,8 @@
 		ast_log(LOG_DEBUG, "Destroying SIP peer %s\n", peer->name);
 
 	/* Delete it, it needs to disappear */
-	if (peer->peer_call)
-		sip_destroy(peer->peer_call);
+	if (peer->peer_pvt)
+		sip_destroy(peer->peer_pvt);
 
 	if (peer->mwi_pvt) 	/* We have an active subscription, delete it */
 		sip_destroy(peer->mwi_pvt);
@@ -3025,13 +3023,13 @@
 	if (option_debug > 2)
 		ast_log(LOG_DEBUG, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname);
 
-	if (reg->call) {
+	if (reg->register_pvt) {
 		/* Clear registry before destroying to ensure
 		   we don't get reentered trying to grab the registry lock */
-		reg->call->registry = NULL;
+		reg->register_pvt->registry = NULL;
 		if (option_debug > 2)
 			ast_log(LOG_DEBUG, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname);
-		sip_destroy(reg->call);
+		sip_destroy(reg->register_pvt);
 	}
 	if (reg->expire > -1)
 		ast_sched_del(sched, reg->expire);
@@ -3109,8 +3107,12 @@
 		p->route = NULL;
 	}
 	if (p->registry) {
-		if (p->registry->call == p)
-			p->registry->call = NULL;
+		/* XXX why this is only for ourselves ?
+		 * in any case, if it is for ourselves, the destructor
+		 * would not be called in astobj2
+		 */
+		if (p->registry->register_pvt == p)
+			p->registry->register_pvt = pvt_unref(p->registry->register_pvt);
 		unref_registry(p->registry);
 	}
 
@@ -3470,9 +3472,9 @@
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);	/* also cancels previous one if there */
 		ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Really hang up next time */
 		ast_clear_flag(&p->flags[0], SIP_NEEDDESTROY);
+		/* XXX assert(p->owner == ast); */
 		if (p->owner->tech_pvt)	/* i believe that's always */
-			pvt_unref(p->owner->tech_pvt);
-		p->owner->tech_pvt = NULL;
+			p->owner->tech_pvt = pvt_unref(p->owner->tech_pvt);
 		p->owner = NULL;  /* Owner will be gone after we return, so take it away */
 		return 0;
 	}
@@ -3510,7 +3512,8 @@
 		ast_dsp_free(p->vad);
 
 	p->owner = NULL;
-	ast->tech_pvt = NULL;
+	if (ast->tech_pvt)
+		ast->tech_pvt = pvt_unref(ast->tech_pvt);
 
 	/* Do not destroy this pvt until we have timeout or
 	   get an answer to the BYE or INVITE/CANCEL 
@@ -7227,13 +7230,15 @@
 {
 	/* if we are here, we know that we need to reregister. */
 	struct sip_registry *r= ASTOBJ_REF((struct sip_registry *) data);
+	struct sip_pvt *pvt;
 
 	/* if we couldn't get a reference to the registry object, punt */
 	if (!r)
 		return 0;
 
-	if (r->call && !ast_test_flag(&r->call->flags[0], SIP_NO_HISTORY))
-		append_history(r->call, "RegistryRenew", "Account: %s@%s", r->username, r->hostname);
+	pvt = r->register_pvt;	/* XXX do we have a lock on it ? */
+	if (pvt && !ast_test_flag(&pvt->flags[0], SIP_NO_HISTORY))
+		append_history(pvt, "RegistryRenew", "Account: %s@%s", r->username, r->hostname);
 	/* Since registry's are only added/removed by the the monitor thread, this
 	   may be overkill to reference/dereference at all here */
 	if (sipdebug)
@@ -7267,17 +7272,18 @@
 	if (!r)
 		return 0;
 
+	p = r->register_pvt;
 	ast_log(LOG_NOTICE, "   -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts); 
-	if (r->call) {
+	if (p) {
 		/* Unlink us, destroy old call.  Locking is not relevant here because all this happens
 		   in the single SIP manager thread. */
-		p = r->call;
 		if (p->registry)
 			unref_registry(p->registry);
-		r->call = NULL;
 		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 		/* Pretend to ACK anything just in case */
 		__sip_pretend_ack(p); /* XXX we need p locked, not sure we have */
+		r->register_pvt = NULL;	/* reference goes away down */
+		sip_destroy(p);
 	}
 	/* If we have a limit, stop registration and give up */
 	if (global_regattempts_max && (r->regattempts > global_regattempts_max)) {
@@ -7313,12 +7319,12 @@
 		return 0;
 	}
 
-	if (r->call) {	/* We have a registration */
+	if (r->register_pvt) {	/* We have a registration */
 		if (!auth) {
 			ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname);
 			return 0;
 		} else {
-			p = pvt_ref(r->call);	/* grab a reference */
+			p = pvt_ref(r->register_pvt);	/* grab a reference */
 			make_our_tag(p->tag, sizeof(p->tag));	/* create a new local tag for every register attempt */
 			ast_string_field_free(p, theirtag);	/* forget their old tag, so we don't match tags when getting response */
 		}
@@ -7358,7 +7364,7 @@
 		else 	/* Set registry port to the port set from the peer definition/srv or default */
 			r->portno = ntohs(p->sa.sin_port);
 		ast_set_flag(&p->flags[0], SIP_OUTGOING);	/* Registration is outgoing call */
-		r->call = pvt_ref(p);			/* Save pointer to SIP packet */
+		r->register_pvt = pvt_ref(p);			/* Save pointer to SIP packet */
 		p->registry = ASTOBJ_REF(r);	/* Add pointer to registry in packet */
 		if (!ast_strlen_zero(r->secret))	/* Secret (password) */
 			ast_string_field_set(p, peersecret, r->secret);
@@ -8974,7 +8980,8 @@
 		ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to));
 		ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by));
 		ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact));
-		referdata->refer_call = NULL;
+		if (referdata->refer_pvt)	/* XXX or sip_destroy() ? */
+			referdata->refer_pvt = pvt_unref(referdata->refer_pvt);
 		/* Set new context */
 		ast_string_field_set(p, context, transfer_context);
 		return 0;
@@ -12005,7 +12012,7 @@
 				break;
 			}
 			if (!strcasecmp(bridgepeer->tech->type,"SIP")) {
-				bridgepvt = (struct sip_pvt*)(bridgepeer->tech_pvt);
+				bridgepvt = bridgepeer->tech_pvt;
 				if (bridgepvt->udptl) {
 					if (p->t38.state == T38_PEER_REINVITE) {
 						sip_handle_t38_reinvite(bridgepeer, p, 0);
@@ -12173,8 +12180,7 @@
 static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
 {
 	int expires, expires_ms;
-	struct sip_registry *r;
-	r=p->registry;
+	struct sip_registry *r = p->registry;
 
 	switch (resp) {
 	case 401:	/* Unauthorized */
@@ -12194,8 +12200,10 @@
 		ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username,p->registry->hostname);
 		if (global_regattempts_max)
 			p->registry->regattempts = global_regattempts_max+1;
-		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
-		r->call = NULL;
+		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+		if (r->register_pvt)	/* XXX are we sure about destroy ? */
+			sip_destroy(r->register_pvt);
+		r->register_pvt = NULL;
 		ast_sched_del(sched, r->timeout);
 		break;
 	case 407:	/* Proxy auth */
@@ -12209,8 +12217,9 @@
 		ast_log(LOG_WARNING, "Got 423 Interval too brief for service %s@%s, minimum is %d seconds\n", p->registry->username, p->registry->hostname, r->expiry);
 		ast_sched_del(sched, r->timeout);
 		r->timeout = -1;
-		if (r->call) {
-			r->call = NULL;
+		if (r->register_pvt) {	/* XXX are we sure about destroy ? */
+			sip_destroy(r->register_pvt);
+			r->register_pvt = NULL;
 			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 		}
 		if (r->expiry > max_expiry) {
@@ -12228,7 +12237,9 @@
 		if (global_regattempts_max)
 			p->registry->regattempts = global_regattempts_max+1;
 		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
-		r->call = NULL;
+		if (r->register_pvt)	/* XXX are we sure about destroy ? */
+			sip_destroy(r->register_pvt);
+		r->register_pvt = NULL;
 		ast_sched_del(sched, r->timeout);
 		break;
 	case 200:	/* 200 OK */
@@ -12250,7 +12261,9 @@
 			ast_sched_del(sched, r->timeout);
 		}
 		r->timeout=-1;
-		r->call = NULL;
+		if (r->register_pvt)	/* XXX are we sure about destroy ? */
+			sip_destroy(r->register_pvt);
+		r->register_pvt = NULL;
 		p->registry = NULL;
 		/* Let this one hang around until we have all the responses */
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -12335,8 +12348,8 @@
 
 	peer->lastms = pingtime;
 	/* XXX do we need to unlink too ? */
-	if (peer->peer_call)
-		peer->peer_call = pvt_unref(peer->peer_call);
+	if (peer->peer_pvt)
+		peer->peer_pvt = pvt_unref(peer->peer_pvt);
 	if (statechanged) {
 		const char *s = is_reachable ? "Reachable" : "Lagged";
 
@@ -13186,7 +13199,7 @@
 	int earlyreplace = 0;
 	int oneleggedreplace = 0;		/* Call with no bridge, propably IVR or voice message */
 	struct ast_channel *c = p->owner;	/* Our incoming call */
-	struct ast_channel *replacecall = p->refer->refer_call->owner;	/* The channel we're about to take over */
+	struct ast_channel *replacecall = p->refer->refer_pvt->owner;	/* The channel we're about to take over */
 	struct ast_channel *targetcall;		/* The bridge to the take-over target */
 
 	/* Check if we're in ring state */
@@ -13220,16 +13233,17 @@
 		transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE);
 		/* Do something more clever here */
 		ast_channel_unlock(c);
-		sip_pvt_unlock(p->refer->refer_call);
+		sip_pvt_unlock(p->refer->refer_pvt);
 		return 1;
 	} 
+	/* XXX this block is wrong here, we already assumed c != NULL above */
 	if (!c) {
 		/* What to do if no channel ??? */
 		ast_log(LOG_ERROR, "Unable to create new channel.  Invite/replace failed.\n");
 		transmit_response_reliable(p, "503 Service Unavailable", req);
 		append_history(p, "Xfer", "INVITE/Replace Failed. No new channel.");
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		sip_pvt_unlock(p->refer->refer_call);
+		sip_pvt_unlock(p->refer->refer_pvt);
 		return 1;
 	}
 	append_history(p, "Xfer", "INVITE/Replace received");
@@ -13263,10 +13277,10 @@
 	ast_channel_unlock(c);
 
 	/* Unlock PVT */
-	sip_pvt_unlock(p->refer->refer_call);
+	sip_pvt_unlock(p->refer->refer_pvt);
 
 	/* Make sure that the masq does not free our PVT for the old call */
-	ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
+	ast_set_flag(&p->refer->refer_pvt->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
 		
 	/* Prepare the masquerade - if this does not happen, we will be gone */
 	if(ast_channel_masquerade(replacecall, c))
@@ -13304,7 +13318,7 @@
 		}
 		ast_channel_unlock(replacecall);
 	}
-	sip_pvt_unlock(p->refer->refer_call);
+	sip_pvt_unlock(p->refer->refer_pvt);
 
 	ast_setstate(c, AST_STATE_DOWN);
 	if (option_debug > 3) {
@@ -13329,7 +13343,12 @@
 	sip_pvt_unlock(p);	/* Unlock SIP structure */
 
 	/* The call should be down with no ast_channel, so hang it up */
-	c->tech_pvt = NULL;	/* XXX do we need unref ? */
+	/* XXX not sure if this is a sip tech or something else.
+	 * do we need to destroy it or what ?
+	 * And why do we reset it before calling hangup ?
+	 */
+	if (c->tech_pvt)
+		c->tech_pvt = pvt_unref(c->tech_pvt);
 	ast_hangup(c);
 	return 0;
 }
@@ -13451,7 +13470,8 @@
 		/* Try to find call that we are replacing 
 			If we have a Replaces  header, we need to cancel that call if we succeed with this call 
 		*/
-		if ((p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) {
+		/* XXX do we have a previous refer_pvt ? */
+		if ((p->refer->refer_pvt = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) {
 			ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id);
 			transmit_response(p, "481 Call Leg Does Not Exist (Replaces)", req);
 			error = 1;
@@ -13463,14 +13483,14 @@
 			We want to bridge the bridged part of the call to the 
 			incoming invite, thus taking over the refered call */
 
-		if (p->refer->refer_call == p) {
+		if (p->refer->refer_pvt == p) {
 			ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid);
-			p->refer->refer_call = pvt_unref(p->refer->refer_call);
+			p->refer->refer_pvt = pvt_unref(p->refer->refer_pvt);
 			transmit_response(p, "400 Bad request", req);	/* The best way to not not accept the transfer */
 			error = 1;
 		}
 
-		if (!error && !p->refer->refer_call->owner) {
+		if (!error && !p->refer->refer_pvt->owner) {
 			/* Oops, someting wrong anyway, no owner, no call */
 			ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id);
 			/* Check for better return code */
@@ -13478,7 +13498,7 @@
 			error = 1;
 		}
 
-		if (!error && p->refer->refer_call->owner->_state != AST_STATE_RING && p->refer->refer_call->owner->_state != AST_STATE_UP ) {
+		if (!error && p->refer->refer_pvt->owner->_state != AST_STATE_RING && p->refer->refer_pvt->owner->_state != AST_STATE_UP ) {
 			ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id);
 			transmit_response(p, "603 Declined (Replaces)", req);
 			error = 1;
@@ -13488,9 +13508,9 @@
 			append_history(p, "Xfer", "INVITE/Replace Failed.");
 			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 			sip_pvt_unlock(p);
-			if (p->refer->refer_call) {
-				sip_pvt_unlock(p->refer->refer_call);
-				ast_channel_unlock(p->refer->refer_call->owner);
+			if (p->refer->refer_pvt) {	/* XXX what's the right order here ? */
+				sip_pvt_unlock(p->refer->refer_pvt);
+				ast_channel_unlock(p->refer->refer_pvt->owner);
 			}
 			return -1;
 		}
@@ -13733,7 +13753,7 @@
 					/* We have a bridge, and this is re-invite to switchover to T38 so we send re-invite with T38 SDP, to other side of bridge*/
 					/*! XXX: we should also check here does the other side supports t38 at all !!! XXX */
 					if (!strcasecmp(bridgepeer->tech->type, "SIP")) { /* If we are bridged to SIP channel */
-						bridgepvt = (struct sip_pvt*)bridgepeer->tech_pvt;
+						bridgepvt = bridgepeer->tech_pvt;
 						if (bridgepvt->t38.state == T38_DISABLED) {
 							if (bridgepvt->udptl) { /* If everything is OK with other side's udptl struct */
 								/* Send re-invite to the bridged channel */
@@ -13785,7 +13805,7 @@
 				struct sip_pvt *bridgepvt = NULL;
 				if ((bridgepeer = ast_bridged_channel(p->owner))) {
 					if (!strcasecmp(bridgepeer->tech->type, sip_tech.type)) {
-						bridgepvt = (struct sip_pvt*)bridgepeer->tech_pvt;
+						bridgepvt = bridgepeer->tech_pvt;
 						/* Does the bridged peer have T38 ? */
 						if (bridgepvt->t38.state == T38_ENABLED) {
 							ast_log(LOG_WARNING, "RTP re-invite after T38 session not handled yet !\n");
@@ -14568,7 +14588,7 @@
 		if (authpeer->mwi_pvt && authpeer->mwi_pvt != p)	/* Destroy old PVT if this is a new one */
 			/* We only allow one subscription per peer */
 			sip_destroy(authpeer->mwi_pvt);
-		authpeer->mwi_pvt = p;		/* Link from peer to pvt */
+		authpeer->mwi_pvt = pvt_ref(p);		/* Link from peer to pvt */
 		p->relatedpeer = authpeer;	/* Link from pvt to peer */
 		/* Do not release authpeer here */
 	} else { /* At this point, Asterisk does not understand the specified event */
@@ -15320,9 +15340,9 @@
 		ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE!  Last qualify: %d\n", peer->name, peer->lastms);
 		manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1);
 	}
-	if (peer->peer_call)
-		sip_destroy(peer->peer_call);
-	peer->peer_call = NULL;
+	if (peer->peer_pvt)
+		sip_destroy(peer->peer_pvt);
+	peer->peer_pvt = NULL;
 	peer->lastms = -1;
 	ast_device_state_changed("SIP/%s", peer->name);
 	/* Try again quickly */
@@ -15344,16 +15364,16 @@
 			ast_sched_del(sched, peer->pokeexpire);
 		peer->lastms = 0;
 		peer->pokeexpire = -1;
-		if (peer->peer_call)	/* XXX or sip_destroy() ? */
-			peer->peer_call = pvt_unref(peer->peer_call);
+		if (peer->peer_pvt)	/* XXX or sip_destroy() ? */
+			peer->peer_pvt = pvt_unref(peer->peer_pvt);
 		return 0;
 	}
-	if (peer->peer_call) {
+	if (peer->peer_pvt) {
 		if (sipdebug)
 			ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
-		sip_destroy(peer->peer_call);
-	}
-	if (!(p = peer->peer_call = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
+		sip_destroy(peer->peer_pvt);
+	}
+	if (!(p = peer->peer_pvt = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
 		return -1;
 	
 	p->sa = peer->addr;
@@ -17294,11 +17314,12 @@
 	/* This is needed, since otherwise active registry entries will not be destroyed */
 	ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
 		ASTOBJ_RDLOCK(iterator);
-		if (iterator->call) {
+		if (iterator->register_pvt) {
 			if (option_debug > 2)
 				ast_log(LOG_DEBUG, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
 			/* This will also remove references to the registry */
-			sip_destroy(iterator->call);
+			sip_destroy(iterator->register_pvt);
+			iterator->register_pvt = NULL;
 		}
 		ASTOBJ_UNLOCK(iterator);
 	} while(0));



More information about the svn-commits mailing list