Lock around variables retrieved, and copy the values, if they stay persistent,
authorTilghman Lesher <tilghman@meg.abyt.es>
Wed, 30 Apr 2008 19:21:04 +0000 (19:21 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Wed, 30 Apr 2008 19:21:04 +0000 (19:21 +0000)
since another thread could remove them.
(closes issue #12541)
 Reported by: snuffy
 Patches:
       bug_12156_apps.diff uploaded by snuffy (license 35)
       Several additional changes by me

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

apps/app_chanspy.c
apps/app_externalivr.c
apps/app_macro.c
apps/app_meetme.c
apps/app_minivm.c
apps/app_morsecode.c
apps/app_speech_utils.c
apps/app_stack.c
apps/app_voicemail.c
apps/app_while.c

index d77fa4b..82c7afc 100644 (file)
@@ -596,12 +596,15 @@ static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
 
        if (ast_test_flag(flags, OPTION_EXIT)) {
                const char *c;
-               if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT")))
+               ast_channel_lock(chan);
+               if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT"))) {
                        ast_copy_string(exitcontext, c, sizeof(exitcontext));
-               else if (!ast_strlen_zero(chan->macrocontext))
+               } else if (!ast_strlen_zero(chan->macrocontext)) {
                        ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext));
-               else
+               } else {
                        ast_copy_string(exitcontext, chan->context, sizeof(exitcontext));
+               }
+               ast_channel_unlock(chan);
        }
 
        ast_mutex_init(&chanspy_ds.lock);
index 3bf7dd1..a93abb4 100644 (file)
@@ -251,10 +251,13 @@ static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *out
                        break;
                }
                
-               value = pbx_builtin_getvar_helper(chan, variable);
-               if(!value)
+               ast_channel_lock(chan);
+               if (!(value = pbx_builtin_getvar_helper(chan, variable))) {
                        value = "";
+               }
+
                ast_str_append(&newstring, 0, "%s=%s,", variable, value);
+               ast_channel_unlock(chan);
                ast_copy_string(outbuf, newstring->str, outbuflen);
        }
 };
index b087ad3..a50dfb4 100644 (file)
@@ -165,20 +165,24 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
        }
 
        /* does the user want a deeper rabbit hole? */
-       s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION");
-       if (s)
+       ast_channel_lock(chan);
+       if ((s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"))) {
                sscanf(s, "%d", &maxdepth);
-
+       }
+       
        /* Count how many levels deep the rabbit hole goes */
-       s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
-       if (s)
+       if ((s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"))) {
                sscanf(s, "%d", &depth);
+       }
+       
        /* Used for detecting whether to return when a Macro is called from another Macro after hangup */
        if (strcmp(chan->exten, "h") == 0)
                pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1");
-       inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP");
-       if (!ast_strlen_zero(inhangupc))
+       
+       if ((inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP"))) {
                sscanf(inhangupc, "%d", &inhangup);
+       }
+       ast_channel_unlock(chan);
 
        if (depth >= maxdepth) {
                ast_log(LOG_ERROR, "Macro():  possible infinite loop detected.  Returning early.\n");
@@ -247,17 +251,19 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
        ast_copy_string(chan->context, fullmacro, sizeof(chan->context));
        chan->priority = 1;
 
+       ast_channel_lock(chan);
        while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
                const char *s;
                /* Save copy of old arguments if we're overwriting some, otherwise
                let them pass through to the other macro */
                snprintf(varname, sizeof(varname), "ARG%d", argc);
-               s = pbx_builtin_getvar_helper(chan, varname);
-               if (s)
+               if ((s = pbx_builtin_getvar_helper(chan, varname))) {
                        oldargs[argc] = ast_strdup(s);
+               }
                pbx_builtin_setvar_helper(chan, varname, cur);
                argc++;
        }
+       ast_channel_unlock(chan);
        autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
        ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
        while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
@@ -431,6 +437,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
                        /* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
                        const char *offsets;
                        ast_copy_string(chan->exten, oldexten, sizeof(chan->exten));
+                       ast_channel_lock(chan);
                        if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
                                /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
                                normally if there is any problem */
@@ -440,6 +447,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
                                        }
                                }
                        }
+                       ast_channel_unlock(chan);
                }
        }
 
index 5e34728..ff52323 100644 (file)
@@ -374,8 +374,8 @@ struct ast_conference {
        pthread_t recordthread;                 /*!< thread for recording */
        ast_mutex_t recordthreadlock;           /*!< control threads trying to start recordthread */
        pthread_attr_t attr;                    /*!< thread attribute */
-       const char *recordingfilename;          /*!< Filename to record the Conference into */
-       const char *recordingformat;            /*!< Format to record the Conference in */
+       char *recordingfilename;                /*!< Filename to record the Conference into */
+       char *recordingformat;                  /*!< Format to record the Conference in */
        char pin[MAX_PIN];                      /*!< If protected by a PIN */
        char pinadmin[MAX_PIN];                 /*!< If protected by a admin PIN */
        char uniqueid[32];
@@ -1350,7 +1350,12 @@ static int conf_free(struct ast_conference *conf)
                ast_hangup(conf->chan);
        if (conf->fd >= 0)
                close(conf->fd);
-
+       if (conf->recordingfilename) {
+               ast_free(conf->recordingfilename);
+       }
+       if (conf->recordingformat) {
+               ast_free(conf->recordingformat);
+       }
        ast_mutex_destroy(&conf->playlock);
        ast_mutex_destroy(&conf->listenlock);
        ast_mutex_destroy(&conf->recordthreadlock);
@@ -1507,8 +1512,8 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        struct timeval now;
        struct ast_dsp *dsp = NULL;
        struct ast_app *app;
-       const char *agifile;
-       const char *agifiledefault = "conf-background.agi";
+       char *agifile;
+       const char *agifiledefault = "conf-background.agi", *tmp;
        char meetmesecs[30] = "";
        char exitcontext[AST_MAX_CONTEXT] = "";
        char recordingtmp[AST_MAX_EXTENSION] = "";
@@ -1575,12 +1580,22 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                                        play_warning = warning_freq = 0;
                        }
                }
-                       
-               var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE");
+               
+               ast_channel_lock(chan);
+               if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) {
+                       var = ast_strdupa(var);
+               }
+               ast_channel_unlock(chan);
+
                warning_sound = var ? var : "timeleft";
                
-               var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE");
-               end_sound = var ? var : NULL;
+               ast_channel_lock(chan);
+               if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) {
+                       var = ast_strdupa(var);
+               }
+               ast_channel_unlock(chan);
+               
+               end_sound = var ? var : NULL;
                        
                /* undo effect of S(x) in case they are both used */
                calldurationlimit = 0;
@@ -1608,15 +1623,21 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        
        if (confflags & CONFFLAG_RECORDCONF) {
                if (!conf->recordingfilename) {
-                       conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE");
+                       const char *var;
+                       ast_channel_lock(chan);
+                       if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) {
+                               conf->recordingfilename = ast_strdup(var);
+                       }
+                       if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) {
+                               conf->recordingformat = ast_strdup(var);
+                       }
+                       ast_channel_unlock(chan);
                        if (!conf->recordingfilename) {
                                snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid);
-                               conf->recordingfilename = ast_strdupa(recordingtmp);
+                               conf->recordingfilename = ast_strdup(recordingtmp);
                        }
-                       conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT");
                        if (!conf->recordingformat) {
-                               ast_copy_string(recordingtmp, "wav", sizeof(recordingtmp));
-                               conf->recordingformat = ast_strdupa(recordingtmp);
+                               conf->recordingformat = ast_strdup("wav");
                        }
                        ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n",
                                    conf->confno, conf->recordingfilename, conf->recordingformat);
@@ -1736,12 +1757,15 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid);
 
        if (confflags & CONFFLAG_EXIT_CONTEXT) {
-               if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 
-                       ast_copy_string(exitcontext, agifile, sizeof(exitcontext));
-               else if (!ast_strlen_zero(chan->macrocontext)) 
+               ast_channel_lock(chan);
+               if ((tmp = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) {
+                       ast_copy_string(exitcontext, tmp, sizeof(exitcontext));
+               } else if (!ast_strlen_zero(chan->macrocontext)) {
                        ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext));
-               else
+               } else {
                        ast_copy_string(exitcontext, chan->context, sizeof(exitcontext));
+               }
+               ast_channel_unlock(chan);
        }
 
        if (!(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) {
@@ -1932,10 +1956,14 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND)
                   or use default filename of conf-background.agi */
 
-               agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND");
-               if (!agifile)
-                       agifile = agifiledefault;
-
+               ast_channel_lock(chan);
+               if ((tmp = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"))) {
+                       agifile = ast_strdupa(tmp);
+               } else {
+                       agifile = ast_strdupa(agifiledefault);
+               }
+               ast_channel_unlock(chan);
+               
                if (user->zapchannel) {
                        /*  Set CONFMUTE mode on Zap channel to mute DTMF tones */
                        x = 1;
@@ -1944,8 +1972,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                /* Find a pointer to the agi app and execute the script */
                app = pbx_findapp("agi");
                if (app) {
-                       char *s = ast_strdupa(agifile);
-                       ret = pbx_exec(chan, app, s);
+                       ret = pbx_exec(chan, app, agifile);
                } else {
                        ast_log(LOG_WARNING, "Could not find application (agi)\n");
                        ret = -2;
index 8a66a95..8746aca 100644 (file)
@@ -1412,7 +1412,12 @@ static int notify_new_message(struct ast_channel *chan, const char *templatename
 
 
        /* Read counter if available */
-       counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER");
+       ast_channel_lock(chan);
+       if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
+               counter = ast_strdupa(counter);
+       }
+       ast_channel_unlock(chan);
+
        if (ast_strlen_zero(counter)) {
                ast_debug(2, "-_-_- MVM_COUNTER not found\n");
        } else {
@@ -1659,14 +1664,24 @@ static int minivm_notify_exec(struct ast_channel *chan, void *data)
                pbx_builtin_setvar_helper(chan, "MINIVM_NOTIFY_STATUS", "FAILED");
                return -1;
        }
-       
-       filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME");
-       format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT");
-       duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION");
+
+       ast_channel_lock(chan);
+       if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
+               filename = ast_strdupa(filename);
+       }
+       ast_channel_unlock(chan);
        /* Notify of new message to e-mail and pager */
        if (!ast_strlen_zero(filename)) {
+               ast_channel_lock(chan); 
+               if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
+                       format = ast_strdupa(format);
+               }
+               if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
+                       duration_string = ast_strdupa(duration_string);
+               }
+               ast_channel_unlock(chan);
                res = notify_new_message(chan, template, vmu, filename, atoi(duration_string), format, chan->cid.cid_num, chan->cid.cid_name);
-       };
+       }
 
        pbx_builtin_setvar_helper(chan, "MINIVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
 
@@ -1928,10 +1943,13 @@ static int minivm_delete_exec(struct ast_channel *chan, void *data)
        int res = 0;
        char filename[BUFSIZ];
                
-       if (!ast_strlen_zero(data))
+       if (!ast_strlen_zero(data)) {
                ast_copy_string(filename, (char *) data, sizeof(filename));
-       else
+       } else {
+               ast_channel_lock(chan);
                ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
+               ast_channel_unlock(chan);
+       }
 
        if (ast_strlen_zero(filename)) {
                ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
index 6c88ed3..455ee04 100644 (file)
@@ -111,16 +111,20 @@ static int morsecode_exec(struct ast_channel *chan, void *data)
        }
 
        /* Use variable MORESEDITLEN, if set (else 80) */
+       ast_channel_lock(chan);
        ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
        if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%d", &ditlen) != 1)) {
                ditlen = 80;
        }
+       ast_channel_unlock(chan);
 
        /* Use variable MORSETONE, if set (else 800) */
+       ast_channel_lock(chan);
        tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
        if (ast_strlen_zero(tonec) || (sscanf(tonec, "%d", &tone) != 1)) {
                tone = 800;
        }
+       ast_channel_unlock(chan);
 
        for (digit = data; *digit; digit++) {
                int digit2 = *digit;
index 6033923..4677c33 100644 (file)
@@ -559,9 +559,11 @@ static int speech_background(struct ast_channel *chan, void *data)
        }
 
        /* See if the maximum DTMF length variable is set... we use a variable in case they want to carry it through their entire dialplan */
-       if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_MAXLEN")) && !ast_strlen_zero(tmp2))
+       ast_channel_lock(chan);
+       if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_MAXLEN")) && !ast_strlen_zero(tmp2)) {
                max_dtmf_len = atoi(tmp2);
-
+       }
+       
        /* See if a terminator is specified */
        if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_TERMINATOR"))) {
                if (ast_strlen_zero(tmp2))
@@ -569,6 +571,7 @@ static int speech_background(struct ast_channel *chan, void *data)
                else
                        dtmf_terminator = tmp2[0];
        }
+       ast_channel_unlock(chan);
 
        /* Before we go into waiting for stuff... make sure the structure is ready, if not - start it again */
        if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
index 7f53aff..56f9465 100644 (file)
@@ -351,8 +351,11 @@ static int local_read(struct ast_channel *chan, const char *cmd, char *data, cha
        frame = AST_LIST_FIRST(oldlist);
        AST_LIST_TRAVERSE(&frame->varshead, variables, entries) {
                if (!strcmp(data, ast_var_name(variables))) {
-                       const char *tmp = pbx_builtin_getvar_helper(chan, data);
+                       const char *tmp;
+                       ast_channel_lock(chan);
+                       tmp = pbx_builtin_getvar_helper(chan, data);
                        ast_copy_string(buf, S_OR(tmp, ""), len);
+                       ast_channel_unlock(chan);
                        break;
                }
        }
index a7ec371..f588c02 100644 (file)
@@ -3522,7 +3522,11 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
        if (tmpptr)
                *tmpptr++ = '\0';
 
-       category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
+       ast_channel_lock(chan);
+       if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
+               category = ast_strdupa(category);
+       }
+       ast_channel_unlock(chan);
 
        ast_debug(3, "Before find_user\n");
        if (!(vmu = find_user(&svm, context, ext))) {
@@ -4741,9 +4745,15 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu,
 {
        char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
        int newmsgs = 0, oldmsgs = 0;
-       const char *category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
+       const char *category;
        char *myserveremail = serveremail;
 
+       ast_channel_lock(chan);
+       if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
+               category = ast_strdupa(category);
+       }
+       ast_channel_unlock(chan);
+
        make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
        make_file(fn, sizeof(fn), todir, msgnum);
        snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
index 1c61d96..36dd17c 100644 (file)
@@ -184,22 +184,19 @@ static int _while_exec(struct ast_channel *chan, void *data, int end)
        memset(my_name, 0, size);
        snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
        
-       if (ast_strlen_zero(label)) {
-               if (end) 
-                       label = used_index;
-               else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
-                       label = new_index;
-                       pbx_builtin_setvar_helper(chan, my_name, label);
-               }
-               
+       ast_channel_lock(chan);
+       if (end) {
+               label = used_index;
+       } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
+               label = new_index;
+               pbx_builtin_setvar_helper(chan, my_name, label);
        }
-       
        snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
-       while_pri = pbx_builtin_getvar_helper(chan, varname);
-       
        if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
+               while_pri = ast_strdupa(while_pri);
                snprintf(end_varname,VAR_SIZE,"END_%s",varname);
        }
+       ast_channel_unlock(chan);
        
 
        if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
@@ -208,7 +205,8 @@ static int _while_exec(struct ast_channel *chan, void *data, int end)
                pbx_builtin_setvar_helper(chan, varname, NULL);
                pbx_builtin_setvar_helper(chan, my_name, NULL);
                snprintf(end_varname,VAR_SIZE,"END_%s",varname);
-               if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
+               ast_channel_lock(chan);
+               if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
                        ast_parseable_goto(chan, goto_str);
                        pbx_builtin_setvar_helper(chan, end_varname, NULL);
                } else {
@@ -220,6 +218,7 @@ static int _while_exec(struct ast_channel *chan, void *data, int end)
                                ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
                        }
                }
+               ast_channel_unlock(chan);
                return res;
        }
 
@@ -230,7 +229,7 @@ static int _while_exec(struct ast_channel *chan, void *data, int end)
                memset(goto_str, 0, size);
                snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
                pbx_builtin_setvar_helper(chan, varname, goto_str);
-       } 
+       }
 
        else if (end && while_pri) {
                /* END of loop */