[Asterisk-cvs] asterisk db.c,1.22,1.23 manager.c,1.113,1.114
markster
markster
Wed Sep 28 19:13:36 CDT 2005
Update of /usr/cvsroot/asterisk
In directory mongoose.digium.com:/tmp/cvs-serv7993
Modified Files:
db.c manager.c
Log Message:
Remove possibility of manager deadlocks from manager actions
Index: db.c
===================================================================
RCS file: /usr/cvsroot/asterisk/db.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- db.c 14 Sep 2005 20:46:49 -0000 1.22
+++ db.c 28 Sep 2005 23:10:13 -0000 1.23
@@ -565,7 +565,6 @@
astman_send_error(s, m, "Database entry not found");
} else {
astman_send_ack(s, m, "Result will follow");
- ast_mutex_lock(&s->lock);
ast_cli(s->fd, "Event: DBGetResponse\r\n"
"Family: %s\r\n"
"Key: %s\r\n"
@@ -573,7 +572,6 @@
"%s"
"\r\n",
family, key, tmp, idText);
- ast_mutex_unlock(&s->lock);
}
return 0;
}
Index: manager.c
===================================================================
RCS file: /usr/cvsroot/asterisk/manager.c,v
retrieving revision 1.113
retrieving revision 1.114
diff -u -d -r1.113 -r1.114
--- manager.c 25 Sep 2005 16:58:56 -0000 1.113
+++ manager.c 28 Sep 2005 23:10:13 -0000 1.114
@@ -255,6 +255,20 @@
{ { "show", "manager", "connected", NULL },
handle_showmanconn, "Show connected manager interface users", showmanconn_help };
+static void free_session(struct mansession *s)
+{
+ struct eventqent *eqe;
+ if (s->fd > -1)
+ close(s->fd);
+ ast_mutex_destroy(&s->__lock);
+ while(s->eventq) {
+ eqe = s->eventq;
+ s->eventq = s->eventq->next;
+ free(eqe);
+ }
+ free(s);
+}
+
static void destroy_session(struct mansession *s)
{
struct mansession *cur, *prev = NULL;
@@ -271,10 +285,7 @@
prev->next = cur->next;
else
sessions = cur->next;
- if (s->fd > -1)
- close(s->fd);
- ast_mutex_destroy(&s->lock);
- free(s);
+ free_session(s);
} else
ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
ast_mutex_unlock(&sessionlock);
@@ -323,18 +334,18 @@
void astman_send_error(struct mansession *s, struct message *m, char *error)
{
char *id = astman_get_header(m,"ActionID");
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
ast_cli(s->fd, "Response: Error\r\n");
if (id && !ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id);
ast_cli(s->fd, "Message: %s\r\n\r\n", error);
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
}
void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg)
{
char *id = astman_get_header(m,"ActionID");
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
ast_cli(s->fd, "Response: %s\r\n", resp);
if (id && !ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id);
@@ -342,7 +353,7 @@
ast_cli(s->fd, "Message: %s\r\n\r\n", msg);
else
ast_cli(s->fd, "\r\n");
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
}
void astman_send_ack(struct mansession *s, struct message *m, char *msg)
@@ -440,10 +451,10 @@
{
int maskint = ast_strings_to_mask(eventmask);
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
if (maskint >= 0)
s->send_events = maskint;
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
return maskint;
}
@@ -559,7 +570,6 @@
if (id && !ast_strlen_zero(id))
snprintf(idText,256,"ActionID: %s\r\n",id);
ast_cli(s->fd, "Response: Success\r\n%s", idText);
- ast_mutex_lock(&s->lock);
ast_mutex_lock(&actionlock);
while (cur) { /* Walk the list of actions */
if ((s->writeperm & cur->authority) == cur->authority)
@@ -568,7 +578,6 @@
}
ast_mutex_unlock(&actionlock);
ast_cli(s->fd, "\r\n");
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -702,13 +711,11 @@
if (!varval2)
varval2 = "";
ast_mutex_unlock(&c->lock);
- ast_mutex_lock(&s->lock);
ast_cli(s->fd, "Response: Success\r\n"
"Variable: %s\r\nValue: %s\r\n" ,varname,varval2);
if (id && !ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id);
ast_cli(s->fd, "\r\n");
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -745,7 +752,6 @@
snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->_bridge->name);
else
bridge[0] = '\0';
- ast_mutex_lock(&s->lock);
if (c->pbx) {
if (c->cdr) {
elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
@@ -791,18 +797,15 @@
c->accountcode,
ast_state2str(c->_state), bridge, c->uniqueid, idText);
}
- ast_mutex_unlock(&s->lock);
ast_mutex_unlock(&c->lock);
if (!all)
break;
c = ast_channel_walk_locked(c);
}
- ast_mutex_lock(&s->lock);
ast_cli(s->fd,
"Event: StatusComplete\r\n"
"%s"
"\r\n",idText);
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -878,18 +881,12 @@
{
char *cmd = astman_get_header(m, "Command");
char *id = astman_get_header(m, "ActionID");
- ast_mutex_lock(&s->lock);
- s->blocking = 1;
- ast_mutex_unlock(&s->lock);
ast_cli(s->fd, "Response: Follows\r\nPrivilege: Command\r\n");
if (id && !ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n", id);
/* FIXME: Wedge a ActionID response in here, waiting for later changes */
ast_cli_command(s->fd, cmd);
ast_cli(s->fd, "--END COMMAND--\r\n\r\n");
- ast_mutex_lock(&s->lock);
- s->blocking = 0;
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -1087,13 +1084,11 @@
if (id && !ast_strlen_zero(id))
snprintf(idText,256,"ActionID: %s\r\n",id);
ret = ast_app_has_voicemail(mailbox, NULL);
- ast_mutex_lock(&s->lock);
ast_cli(s->fd, "Response: Success\r\n"
"%s"
"Message: Mailbox Status\r\n"
"Mailbox: %s\r\n"
"Waiting: %d\r\n\r\n", idText, mailbox, ret);
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -1119,10 +1114,9 @@
return 0;
}
ast_app_messagecount(mailbox, &newmsgs, &oldmsgs);
- if (id && !ast_strlen_zero(id)) {
- snprintf(idText,256,"ActionID: %s\r\n",id);
- }
- ast_mutex_lock(&s->lock);
+ if (id && !ast_strlen_zero(id)) {
+ snprintf(idText,256,"ActionID: %s\r\n",id);
+ }
ast_cli(s->fd, "Response: Success\r\n"
"%s"
"Message: Mailbox Message Count\r\n"
@@ -1131,7 +1125,6 @@
"OldMessages: %d\r\n"
"\r\n",
idText,mailbox, newmsgs, oldmsgs);
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -1165,7 +1158,6 @@
if (id && !ast_strlen_zero(id)) {
snprintf(idText,256,"ActionID: %s\r\n",id);
}
- ast_mutex_lock(&s->lock);
ast_cli(s->fd, "Response: Success\r\n"
"%s"
"Message: Extension Status\r\n"
@@ -1174,7 +1166,6 @@
"Hint: %s\r\n"
"Status: %d\r\n\r\n",
idText,exten, context, hint, status);
- ast_mutex_unlock(&s->lock);
return 0;
}
@@ -1233,16 +1224,16 @@
authtype = astman_get_header(m, "AuthType");
if (!strcasecmp(authtype, "MD5")) {
if (!s->challenge || ast_strlen_zero(s->challenge)) {
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
snprintf(s->challenge, sizeof(s->challenge), "%d", rand());
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
}
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
ast_cli(s->fd, "Response: Success\r\n"
"%s"
"Challenge: %s\r\n\r\n",
idText,s->challenge);
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
return 0;
} else {
astman_send_error(s, m, "Must specify AuthType");
@@ -1269,19 +1260,40 @@
} else
astman_send_error(s, m, "Authentication Required");
} else {
+ int ret=0;
+ struct eventqent *eqe;
+ ast_mutex_lock(&s->__lock);
+ s->busy = 1;
+ ast_mutex_unlock(&s->__lock);
while( tmp ) {
if (!strcasecmp(action, tmp->action)) {
if ((s->writeperm & tmp->authority) == tmp->authority) {
if (tmp->func(s, m))
- return -1;
+ ret = -1;
} else {
astman_send_error(s, m, "Permission denied");
}
- return 0;
+ break;
}
tmp = tmp->next;
}
- astman_send_error(s, m, "Invalid/unknown command");
+ ast_mutex_lock(&s->__lock);
+ s->busy = 0;
+ while(s->eventq) {
+ if (ast_carefulwrite(s->fd, s->eventq->eventdata, strlen(s->eventq->eventdata), 100)) {
+ ret = -1;
+ break;
+ }
+ eqe = s->eventq;
+ s->eventq = s->eventq->next;
+ free(eqe);
+ }
+ ast_mutex_unlock(&s->__lock);
+ if (!ret)
+ astman_send_error(s, m, "Invalid/unknown command");
+ else
+ ret = 0;
+ return ret;
}
return 0;
}
@@ -1319,9 +1331,9 @@
ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
return -1;
} else if (res > 0) {
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
if (res < 1)
return -1;
break;
@@ -1339,9 +1351,9 @@
char iabuf[INET_ADDRSTRLEN];
int res;
- ast_mutex_lock(&s->lock);
+ ast_mutex_lock(&s->__lock);
ast_cli(s->fd, "Asterisk Call Manager/1.0\r\n");
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
memset(&m, 0, sizeof(&m));
for (;;) {
res = get_input(s, m.headers[m.hdrcount]);
@@ -1416,7 +1428,7 @@
flags = fcntl(as, F_GETFL);
fcntl(as, F_SETFL, flags | O_NONBLOCK);
}
- ast_mutex_init(&s->lock);
+ ast_mutex_init(&s->__lock);
s->fd = as;
s->send_events = -1;
ast_mutex_lock(&sessionlock);
@@ -1430,36 +1442,71 @@
return NULL;
}
+static int append_event(struct mansession *s, const char *str)
+{
+ struct eventqent *tmp, *prev=NULL;
+ tmp = malloc(sizeof(struct eventqent) + strlen(str));
+ if (tmp) {
+ tmp->next = NULL;
+ strcpy(tmp->eventdata, str);
+ if (s->eventq) {
+ prev = s->eventq;
+ while(prev->next)
+ prev = prev->next;
+ prev->next = tmp;
+ } else {
+ s->eventq = tmp;
+ }
+ return 0;
+ }
+ return -1;
+}
+
/*--- manager_event: Send AMI event to client */
int manager_event(int category, char *event, char *fmt, ...)
{
struct mansession *s;
char tmp[4096];
va_list ap;
+ struct mansession *next, *prev = NULL;
ast_mutex_lock(&sessionlock);
s = sessions;
while(s) {
+ next = s->next;
if (((s->readperm & category) == category) && ((s->send_events & category) == category) ) {
- ast_mutex_lock(&s->lock);
- if (!s->blocking) {
- ast_cli(s->fd, "Event: %s\r\n", event);
- ast_cli(s->fd, "Privilege: %s\r\n", authority_to_str(category, tmp, sizeof(tmp)));
- va_start(ap, fmt);
- vsnprintf(tmp, sizeof(tmp), fmt, ap);
- va_end(ap);
- ast_carefulwrite(s->fd,tmp,strlen(tmp),100);
- ast_cli(s->fd, "\r\n");
+ ast_mutex_lock(&s->__lock);
+ ast_cli(s->fd, "Event: %s\r\n", event);
+ ast_cli(s->fd, "Privilege: %s\r\n", authority_to_str(category, tmp, sizeof(tmp)));
+ va_start(ap, fmt);
+ vsnprintf(tmp, sizeof(tmp) - 3, fmt, ap);
+ va_end(ap);
+ strcat(tmp, "\r\n");
+ if (s->busy) {
+ append_event(s, tmp);
+ } else if (ast_carefulwrite(s->fd,tmp,strlen(tmp),100) < 0) {
+ ast_log(LOG_WARNING, "Disconnecting slow manager session!\n");
+ /* Unlink from list */
+ if (prev)
+ prev->next = next;
+ else
+ sessions = next;
+ ast_mutex_unlock(&s->__lock);
+ free_session(s);
+ s = next;
+ continue;
}
- ast_mutex_unlock(&s->lock);
+ ast_mutex_unlock(&s->__lock);
}
- s = s->next;
+ prev = s;
+ s = next;
}
ast_mutex_unlock(&sessionlock);
return 0;
}
-int ast_manager_unregister( char *action ) {
+int ast_manager_unregister( char *action )
+{
struct manager_action *cur = first_action, *prev = first_action;
ast_mutex_lock(&actionlock);
More information about the svn-commits
mailing list