- Don't lock the dialoglist during the whole destruction of a single SIP dialog. Only

lock when needed - when we remove the dialog from the dialog list
  If this doesn't lead to severe problems, it might help with some locking issues
  in 1.4/1.2.
- Remove the term "interface" as a synonym for a SIP dialog. Sorry, Mark, but no
  one understands it... ;-)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@46379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Olle Johansson 2006-10-28 17:25:23 +00:00
parent 6948019465
commit 0f9a1b19f1

View file

@ -561,7 +561,7 @@ static int regobjs = 0; /*!< Registry objects */
static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */ static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */
/*! \brief Protect the SIP dialog list (of sip_pvt's) */ /*! \brief Protect the SIP dialog list (of sip_pvt's) */
AST_MUTEX_DEFINE_STATIC(iflock); AST_MUTEX_DEFINE_STATIC(dialoglock);
AST_MUTEX_DEFINE_STATIC(netlock); AST_MUTEX_DEFINE_STATIC(netlock);
@ -989,7 +989,7 @@ struct sip_pvt {
int autoframing; int autoframing;
}; };
static struct sip_pvt *iflist = NULL; static struct sip_pvt *dialoglist = NULL;
#define FLAG_RESPONSE (1 << 0) #define FLAG_RESPONSE (1 << 0)
#define FLAG_FATAL (1 << 1) #define FLAG_FATAL (1 << 1)
@ -2970,12 +2970,15 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
p->history = NULL; p->history = NULL;
} }
for (prev = NULL, cur = iflist; cur; prev = cur, cur = cur->next) { /* Lock dialog list before removing ourselves from the list */
ast_mutex_lock(&dialoglock);
for (prev = NULL, cur = dialoglist; cur; prev = cur, cur = cur->next) {
if (cur == p) { if (cur == p) {
UNLINK(cur, iflist, prev); UNLINK(cur, dialoglist, prev);
break; break;
} }
} }
ast_mutex_unlock(&dialoglock);
if (!cur) { if (!cur) {
ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid); ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid);
return; return;
@ -3121,11 +3124,9 @@ static int update_call_counter(struct sip_pvt *fup, int event)
/*! \brief Destroy SIP call structure */ /*! \brief Destroy SIP call structure */
static void sip_destroy(struct sip_pvt *p) static void sip_destroy(struct sip_pvt *p)
{ {
ast_mutex_lock(&iflock);
if (option_debug > 2) if (option_debug > 2)
ast_log(LOG_DEBUG, "Destroying SIP dialog %s\n", p->callid); ast_log(LOG_DEBUG, "Destroying SIP dialog %s\n", p->callid);
__sip_destroy(p, 1); __sip_destroy(p, 1);
ast_mutex_unlock(&iflock);
} }
/*! \brief Convert SIP hangup causes to Asterisk hangup causes */ /*! \brief Convert SIP hangup causes to Asterisk hangup causes */
@ -4288,10 +4289,10 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
ast_string_field_set(p, context, default_context); ast_string_field_set(p, context, default_context);
/* Add to active dialog list */ /* Add to active dialog list */
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
p->next = iflist; p->next = dialoglist;
iflist = p; dialoglist = p;
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : "(No Call-ID)", sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP"); ast_log(LOG_DEBUG, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : "(No Call-ID)", sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP");
return p; return p;
@ -4333,8 +4334,8 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
ast_log(LOG_DEBUG, "= Looking for Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag); ast_log(LOG_DEBUG, "= Looking for Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag);
} }
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
for (p = iflist; p; p = p->next) { for (p = dialoglist; p; p = p->next) {
/* In pedantic, we do not want packets with bad syntax to be connected to a PVT */ /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */
int found = FALSE; int found = FALSE;
if (req->method == SIP_REGISTER) if (req->method == SIP_REGISTER)
@ -4364,11 +4365,11 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
if (found) { if (found) {
/* Found the call */ /* Found the call */
sip_pvt_lock(p); sip_pvt_lock(p);
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
return p; return p;
} }
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
/* See if the method is capable of creating a dialog */ /* See if the method is capable of creating a dialog */
if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) { if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
@ -8494,7 +8495,7 @@ static int get_destination(struct sip_pvt *p, struct sip_request *oreq)
return -1; return -1;
} }
/*! \brief Lock interface lock and find matching pvt lock /*! \brief Lock dialog lock and find matching pvt lock
- Their tag is fromtag, our tag is to-tag - Their tag is fromtag, our tag is to-tag
- This means that in some transactions, totag needs to be their tag :-) - This means that in some transactions, totag needs to be their tag :-)
depending upon the direction depending upon the direction
@ -8503,13 +8504,13 @@ static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *t
{ {
struct sip_pvt *sip_pvt_ptr; struct sip_pvt *sip_pvt_ptr;
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
if (option_debug > 3 && totag) if (option_debug > 3 && totag)
ast_log(LOG_DEBUG, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>"); ast_log(LOG_DEBUG, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>");
/* Search interfaces and find the match */ /* Search dialogs and find the match */
for (sip_pvt_ptr = iflist; sip_pvt_ptr; sip_pvt_ptr = sip_pvt_ptr->next) { for (sip_pvt_ptr = dialoglist; sip_pvt_ptr; sip_pvt_ptr = sip_pvt_ptr->next) {
if (!strcmp(sip_pvt_ptr->callid, callid)) { if (!strcmp(sip_pvt_ptr->callid, callid)) {
int match = 1; int match = 1;
char *ourtag = sip_pvt_ptr->tag; char *ourtag = sip_pvt_ptr->tag;
@ -8543,7 +8544,7 @@ static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *t
break; break;
} }
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
if (option_debug > 3 && !sip_pvt_ptr) if (option_debug > 3 && !sip_pvt_ptr)
ast_log(LOG_DEBUG, "Found no match for callid %s to-tag %s from-tag %s\n", callid, totag, fromtag); ast_log(LOG_DEBUG, "Found no match for callid %s to-tag %s from-tag %s\n", callid, totag, fromtag);
return sip_pvt_ptr; return sip_pvt_ptr;
@ -10404,8 +10405,8 @@ static int __sip_show_channels(int fd, int argc, char *argv[], int subscriptions
if (argc != 3) if (argc != 3)
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
cur = iflist; cur = dialoglist;
if (!subscriptions) if (!subscriptions)
ast_cli(fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Seq (Tx/Rx)", "Format", "Hold", "Last Message"); ast_cli(fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Seq (Tx/Rx)", "Format", "Hold", "Last Message");
else else
@ -10441,7 +10442,7 @@ static int __sip_show_channels(int fd, int argc, char *argv[], int subscriptions
numchans++; numchans++;
} }
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
if (!subscriptions) if (!subscriptions)
ast_cli(fd, "%d active SIP channel%s\n", numchans, (numchans != 1) ? "s" : ""); ast_cli(fd, "%d active SIP channel%s\n", numchans, (numchans != 1) ? "s" : "");
else else
@ -10460,14 +10461,14 @@ static char *complete_sipch(const char *line, const char *word, int pos, int sta
char *c = NULL; char *c = NULL;
int wordlen = strlen(word); int wordlen = strlen(word);
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
for (cur = iflist; cur; cur = cur->next) { for (cur = dialoglist; cur; cur = cur->next) {
if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) { if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) {
c = ast_strdup(cur->callid); c = ast_strdup(cur->callid);
break; break;
} }
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
return c; return c;
} }
@ -10592,8 +10593,8 @@ static int sip_show_channel(int fd, int argc, char *argv[])
if (argc != 4) if (argc != 4)
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
len = strlen(argv[3]); len = strlen(argv[3]);
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
for (cur = iflist; cur; cur = cur->next) { for (cur = dialoglist; cur; cur = cur->next) {
if (!strncasecmp(cur->callid, argv[3], len)) { if (!strncasecmp(cur->callid, argv[3], len)) {
char formatbuf[BUFSIZ/2]; char formatbuf[BUFSIZ/2];
ast_cli(fd,"\n"); ast_cli(fd,"\n");
@ -10646,7 +10647,7 @@ static int sip_show_channel(int fd, int argc, char *argv[])
found++; found++;
} }
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
if (!found) if (!found)
ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]); ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]);
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -10664,8 +10665,8 @@ static int sip_show_history(int fd, int argc, char *argv[])
if (!recordhistory) if (!recordhistory)
ast_cli(fd, "\n***Note: History recording is currently DISABLED. Use 'sip history' to ENABLE.\n"); ast_cli(fd, "\n***Note: History recording is currently DISABLED. Use 'sip history' to ENABLE.\n");
len = strlen(argv[3]); len = strlen(argv[3]);
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
for (cur = iflist; cur; cur = cur->next) { for (cur = dialoglist; cur; cur = cur->next) {
if (!strncasecmp(cur->callid, argv[3], len)) { if (!strncasecmp(cur->callid, argv[3], len)) {
struct sip_history *hist; struct sip_history *hist;
int x = 0; int x = 0;
@ -10683,7 +10684,7 @@ static int sip_show_history(int fd, int argc, char *argv[])
found++; found++;
} }
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
if (!found) if (!found)
ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]); ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]);
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -14303,8 +14304,8 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
for it to expire and send NOTIFY messages to the peer only to have them for it to expire and send NOTIFY messages to the peer only to have them
ignored (or generate errors) ignored (or generate errors)
*/ */
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
for (p_old = iflist; p_old; p_old = p_old->next) { for (p_old = dialoglist; p_old; p_old = p_old->next) {
if (p_old == p) if (p_old == p)
continue; continue;
if (p_old->initreq.method != SIP_SUBSCRIBE) if (p_old->initreq.method != SIP_SUBSCRIBE)
@ -14322,7 +14323,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
} }
sip_pvt_unlock(p_old); sip_pvt_unlock(p_old);
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
} }
if (!p->expiry) if (!p->expiry)
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
@ -14833,15 +14834,15 @@ static void *do_monitor(void *data)
if (sipsock > -1) if (sipsock > -1)
sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL); sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL);
} }
/* Check for interfaces needing to be killed */ /* Check for dialogs needing to be killed */
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
restartsearch: restartsearch:
t = time(NULL); t = time(NULL);
/* don't scan the interface list if it hasn't been a reasonable period /* don't scan the dialogs list if it hasn't been a reasonable period
of time since the last time we did it (when MWI is being sent, we can of time since the last time we did it (when MWI is being sent, we can
get back to this point every millisecond or less) get back to this point every millisecond or less)
*/ */
for (sip = iflist; !fastrestart && sip; sip = sip->next) { for (sip = dialoglist; !fastrestart && sip; sip = sip->next) {
sip_pvt_lock(sip); sip_pvt_lock(sip);
/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */ /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
check_rtp_timeout(sip, t); check_rtp_timeout(sip, t);
@ -14854,7 +14855,7 @@ restartsearch:
} }
sip_pvt_unlock(sip); sip_pvt_unlock(sip);
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
pthread_testcancel(); pthread_testcancel();
/* Wait for sched or io */ /* Wait for sched or io */
@ -16025,7 +16026,7 @@ static int reload_config(enum channelreloadreason reason)
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue; continue;
/* Create the interface list */ /* Create the dialogs list */
if (!strcasecmp(v->name, "context")) { if (!strcasecmp(v->name, "context")) {
ast_copy_string(default_context, v->value, sizeof(default_context)); ast_copy_string(default_context, v->value, sizeof(default_context));
} else if (!strcasecmp(v->name, "realm")) { } else if (!strcasecmp(v->name, "realm")) {
@ -17163,13 +17164,13 @@ static int unload_module(void)
ast_manager_unregister("SIPpeers"); ast_manager_unregister("SIPpeers");
ast_manager_unregister("SIPshowpeer"); ast_manager_unregister("SIPshowpeer");
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
/* Hangup all interfaces if they have an owner */ /* Hangup all dialogs if they have an owner */
for (p = iflist; p ; p = p->next) { for (p = dialoglist; p ; p = p->next) {
if (p->owner) if (p->owner)
ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
ast_mutex_lock(&monlock); ast_mutex_lock(&monlock);
if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
@ -17180,9 +17181,9 @@ static int unload_module(void)
monitor_thread = AST_PTHREADT_STOP; monitor_thread = AST_PTHREADT_STOP;
ast_mutex_unlock(&monlock); ast_mutex_unlock(&monlock);
ast_mutex_lock(&iflock); ast_mutex_lock(&dialoglock);
/* Destroy all the interfaces and free their memory */ /* Destroy all the dialogs and free their memory */
p = iflist; p = dialoglist;
while (p) { while (p) {
pl = p; pl = p;
p = p->next; p = p->next;
@ -17194,8 +17195,8 @@ static int unload_module(void)
} }
free(pl); free(pl);
} }
iflist = NULL; dialoglist = NULL;
ast_mutex_unlock(&iflock); ast_mutex_unlock(&dialoglock);
/* Free memory for local network address mask */ /* Free memory for local network address mask */
ast_free_ha(localaddr); ast_free_ha(localaddr);