Merged revisions 177536 via svnmerge from
authorTilghman Lesher <tilghman@meg.abyt.es>
Thu, 19 Feb 2009 22:33:00 +0000 (22:33 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Thu, 19 Feb 2009 22:33:00 +0000 (22:33 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r177536 | tilghman | 2009-02-19 16:26:01 -0600 (Thu, 19 Feb 2009) | 7 lines

  Fix up potential crashes, by reducing the sharing between interactive and non-interactive threads.
  (closes issue #14253)
   Reported by: Skavin
   Patches:
         20090219__bug14253.diff.txt uploaded by Corydon76 (license 14)
   Tested by: Skavin
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@177537 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_voicemail.c

index 257ebae..8cfe1c9 100644 (file)
@@ -115,6 +115,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/res_odbc.h"
 #endif
 
+#ifdef IMAP_STORAGE
+#include "asterisk/threadstorage.h"
+#endif
+
 /*** DOCUMENTATION
        <application name="VoiceMail" language="en_US">
                <synopsis>
@@ -297,6 +301,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  ***/
 
 #ifdef IMAP_STORAGE
+AST_MUTEX_DEFINE_STATIC(imaptemp_lock);
+static char imaptemp[1024];
 static char imapserver[48];
 static char imapport[8];
 static char imapflags[128];
@@ -313,6 +319,8 @@ static char delimiter = '\0';
 struct vm_state;
 struct ast_vm_user;
 
+AST_THREADSTORAGE(ts_vmstate, ts_vmstate_init);
+
 /* Forward declarations for IMAP */
 static int init_mailstream(struct vm_state *vms, int box);
 static void write_file(char *filename, char *buffer, unsigned long len);
@@ -2496,7 +2504,7 @@ static void mm_parsequota(MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pqu
                pquota = pquota->next;
        }
        
-       if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 2))) {
+       if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))) || (!(vms = get_vm_state_by_imapuser(user, 2)) && !(vms = get_vm_state_by_imapuser(user, 0)))) {
                ast_log(AST_LOG_ERROR, "No state found.\n");
                return;
        }
@@ -2559,6 +2567,9 @@ static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu)
 {
        struct vm_state *vms_p;
 
+       if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->username, vmu->mailbox)) {
+               return vms_p;
+       }
        if (option_debug > 4)
                ast_log(AST_LOG_DEBUG,"Adding new vmstate for %s\n",vmu->imapuser);
        if (!(vms_p = ast_calloc(1, sizeof(*vms_p))))
@@ -2581,6 +2592,12 @@ static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
 {
        struct vmstate *vlist = NULL;
 
+       if (interactive) {
+               struct vm_state *vms;
+               vms = pthread_getspecific(ts_vmstate.key);
+               return vms;
+       }
+
        AST_LIST_LOCK(&vmstates);
        AST_LIST_TRAVERSE(&vmstates, vlist, list) {
                if (!vlist->vms) {
@@ -2610,6 +2627,12 @@ static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, const char
        struct vmstate *vlist = NULL;
        const char *local_context = S_OR(context, "default");
 
+       if (interactive) {
+               struct vm_state *vms;
+               vms = pthread_getspecific(ts_vmstate.key);
+               return vms;
+       }
+
        AST_LIST_LOCK(&vmstates);
        AST_LIST_TRAVERSE(&vmstates, vlist, list) {
                if (!vlist->vms) {
@@ -2656,9 +2679,13 @@ static void vmstate_insert(struct vm_state *vms)
                        /* get a pointer to the persistent store */
                        vms->persist_vms = altvms;
                        /* Reuse the mailstream? */
+#ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS
                        vms->mailstream = altvms->mailstream;
-                       /* vms->mailstream = NIL; */
+#else
+                       vms->mailstream = NIL;
+#endif
                }
+               return;
        }
 
        if (!(v = ast_calloc(1, sizeof(*v))))
@@ -2685,6 +2712,10 @@ static void vmstate_delete(struct vm_state *vms)
                altvms->newmessages = vms->newmessages;
                altvms->oldmessages = vms->oldmessages;
                altvms->updated = 1;
+               vms->mailstream = mail_close(vms->mailstream);
+
+               /* Interactive states are not stored within the persistent list */
+               return;
        }
        
        ast_debug(3, "Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->username);
@@ -8892,6 +8923,9 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        adsi_begin(chan, &useadsi);
 
 #ifdef IMAP_STORAGE
+       pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
+       pthread_setspecific(ts_vmstate.key, &vms);
+
        vms.interactive = 1;
        vms.updated = 1;
        if (vmu)
@@ -9462,6 +9496,9 @@ out:
        if (vms.heard)
                ast_free(vms.heard);
 
+#ifdef IMAP_STORAGE
+       pthread_setspecific(ts_vmstate.key, NULL);
+#endif
        return res;
 }