Add additional memory debugging to several core APIs, and fix several memory
leaks found with these changes. (Closes issue #13505, closes issue #13543) Reported by: mav3rick, triccyx Patches: 20081001__bug13505.diff.txt uploaded by Corydon76 (license 14) Tested by: mav3rick, triccyx git-svn-id: http://svn.digium.com/svn/asterisk/trunk@149199 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
d12237922a
commit
6c7d8c95df
|
@ -21820,6 +21820,12 @@ static int reload_config(enum channelreloadreason reason)
|
|||
}
|
||||
|
||||
/* Reset certificate handling for TLS sessions */
|
||||
if (reason != CHANNEL_MODULE_LOAD) {
|
||||
ast_free(default_tls_cfg.certfile);
|
||||
ast_free(default_tls_cfg.cipher);
|
||||
ast_free(default_tls_cfg.cafile);
|
||||
ast_free(default_tls_cfg.capath);
|
||||
}
|
||||
default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */
|
||||
default_tls_cfg.cipher = ast_strdup("");
|
||||
default_tls_cfg.cafile = ast_strdup("");
|
||||
|
|
|
@ -33,7 +33,12 @@ struct ast_var_t {
|
|||
|
||||
AST_LIST_HEAD_NOLOCK(varshead, ast_var_t);
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
struct ast_var_t *_ast_var_assign(const char *name, const char *value, const char *file, int lineno, const char *function);
|
||||
#define ast_var_assign(a,b) _ast_var_assign(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
|
||||
#else
|
||||
struct ast_var_t *ast_var_assign(const char *name, const char *value);
|
||||
#endif
|
||||
void ast_var_delete(struct ast_var_t *var);
|
||||
const char *ast_var_name(const struct ast_var_t *var);
|
||||
const char *ast_var_full_name(const struct ast_var_t *var);
|
||||
|
|
|
@ -364,7 +364,12 @@ void ast_category_destroy(struct ast_category *cat);
|
|||
struct ast_variable *ast_category_detach_variables(struct ast_category *cat);
|
||||
void ast_category_rename(struct ast_category *cat, const char *name);
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
struct ast_variable *_ast_variable_new(const char *name, const char *value, const char *filename, const char *file, const char *function, int lineno);
|
||||
#define ast_variable_new(a, b, c) _ast_variable_new(a, b, c, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#else
|
||||
struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename);
|
||||
#endif
|
||||
struct ast_config_include *ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size);
|
||||
struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file);
|
||||
void ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file);
|
||||
|
|
|
@ -189,12 +189,22 @@ unsigned int ast_hashtab_hash_short(const short num);
|
|||
* \param hash a func ptr to do the hashing
|
||||
* \param do_locking use locks to guarantee safety of iterators/insertion/deletion -- real simpleminded right now
|
||||
*/
|
||||
#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
|
||||
struct ast_hashtab * _ast_hashtab_create(int initial_buckets,
|
||||
int (*compare)(const void *a, const void *b),
|
||||
int (*resize)(struct ast_hashtab *),
|
||||
int (*newsize)(struct ast_hashtab *tab),
|
||||
unsigned int (*hash)(const void *obj),
|
||||
int do_locking, const char *file, int lineno, const char *function);
|
||||
#define ast_hashtab_create(a,b,c,d,e,f) _ast_hashtab_create(a,b,c,d,e,f,__FILE__,__LINE__,__PRETTY_FUNCTION__)
|
||||
#else
|
||||
struct ast_hashtab * ast_hashtab_create(int initial_buckets,
|
||||
int (*compare)(const void *a, const void *b),
|
||||
int (*resize)(struct ast_hashtab *),
|
||||
int (*newsize)(struct ast_hashtab *tab),
|
||||
unsigned int (*hash)(const void *obj),
|
||||
int do_locking );
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief This func will free the hash table and all its memory.
|
||||
|
|
|
@ -404,6 +404,30 @@ void ast_str_reset(struct ast_str *buf),
|
|||
/*!
|
||||
* Make space in a new string (e.g. to read in data from a file)
|
||||
*/
|
||||
#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
|
||||
AST_INLINE_API(
|
||||
int _ast_str_make_space(struct ast_str **buf, size_t new_len, const char *file, int lineno, const char *function),
|
||||
{
|
||||
_DB1(struct ast_str *old_buf = *buf;)
|
||||
|
||||
if (new_len <= (*buf)->len)
|
||||
return 0; /* success */
|
||||
if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC)
|
||||
return -1; /* cannot extend */
|
||||
*buf = (struct ast_str *)__ast_realloc(*buf, new_len + sizeof(struct ast_str), file, lineno, function);
|
||||
if (*buf == NULL) /* XXX watch out, we leak memory here */
|
||||
return -1;
|
||||
if ((*buf)->ts != DS_MALLOC) {
|
||||
pthread_setspecific((*buf)->ts->key, *buf);
|
||||
_DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));)
|
||||
}
|
||||
|
||||
(*buf)->len = new_len;
|
||||
return 0;
|
||||
}
|
||||
)
|
||||
#define ast_str_make_space(a,b) _ast_str_make_space(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
|
||||
#else
|
||||
AST_INLINE_API(
|
||||
int ast_str_make_space(struct ast_str **buf, size_t new_len),
|
||||
{
|
||||
|
@ -425,6 +449,7 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len),
|
|||
return 0;
|
||||
}
|
||||
)
|
||||
#endif
|
||||
|
||||
#define ast_str_alloca(init_len) \
|
||||
({ \
|
||||
|
|
|
@ -31,13 +31,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/strings.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
struct ast_var_t *_ast_var_assign(const char *name, const char *value, const char *file, int lineno, const char *function)
|
||||
#else
|
||||
struct ast_var_t *ast_var_assign(const char *name, const char *value)
|
||||
#endif
|
||||
{
|
||||
struct ast_var_t *var;
|
||||
int name_len = strlen(name) + 1;
|
||||
int value_len = strlen(value) + 1;
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
if (!(var = __ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char), file, lineno, function))) {
|
||||
#else
|
||||
if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -230,14 +230,22 @@ struct ast_config_include {
|
|||
struct ast_config_include *next; /*!< ptr to next inclusion in the list */
|
||||
};
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
struct ast_variable *_ast_variable_new(const char *name, const char *value, const char *filename, const char *file, const char *func, int lineno)
|
||||
#else
|
||||
struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
|
||||
#endif
|
||||
{
|
||||
struct ast_variable *variable;
|
||||
int name_len = strlen(name) + 1;
|
||||
int val_len = strlen(value) + 1;
|
||||
int fn_len = strlen(filename) + 1;
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
if ((variable = __ast_calloc(1, name_len + val_len + fn_len + sizeof(*variable), file, lineno, func))) {
|
||||
#else
|
||||
if ((variable = ast_calloc(1, name_len + val_len + fn_len + sizeof(*variable)))) {
|
||||
#endif
|
||||
char *dst = variable->stuff; /* writable space starts here */
|
||||
variable->name = strcpy(dst, name);
|
||||
dst += name_len;
|
||||
|
|
|
@ -209,22 +209,40 @@ unsigned int ast_hashtab_hash_short(const short x)
|
|||
return x;
|
||||
}
|
||||
|
||||
struct ast_hashtab *ast_hashtab_create(int initial_buckets,
|
||||
struct ast_hashtab *
|
||||
#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
|
||||
_ast_hashtab_create
|
||||
#else
|
||||
ast_hashtab_create
|
||||
#endif
|
||||
(int initial_buckets,
|
||||
int (*compare)(const void *a, const void *b),
|
||||
int (*resize)(struct ast_hashtab *),
|
||||
int (*newsize)(struct ast_hashtab *tab),
|
||||
unsigned int (*hash)(const void *obj),
|
||||
int do_locking)
|
||||
int do_locking
|
||||
#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
|
||||
, const char *file, int lineno, const char *function
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct ast_hashtab *ht;
|
||||
|
||||
|
||||
#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
|
||||
if (!(ht = __ast_calloc(1, sizeof(*ht), file, lineno, function)))
|
||||
#else
|
||||
if (!(ht = ast_calloc(1, sizeof(*ht))))
|
||||
#endif
|
||||
return NULL;
|
||||
|
||||
while (!ast_is_prime(initial_buckets)) /* make sure this is prime */
|
||||
initial_buckets++;
|
||||
|
||||
#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
|
||||
if (!(ht->array = __ast_calloc(initial_buckets, sizeof(*(ht->array)), file, lineno, function))) {
|
||||
#else
|
||||
if (!(ht->array = ast_calloc(initial_buckets, sizeof(*(ht->array))))) {
|
||||
#endif
|
||||
free(ht);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,9 @@ static void init_outgoing(struct outgoing *o)
|
|||
|
||||
static void free_outgoing(struct outgoing *o)
|
||||
{
|
||||
if (o->vars) {
|
||||
ast_variables_destroy(o->vars);
|
||||
}
|
||||
ast_free(o);
|
||||
}
|
||||
|
||||
|
@ -324,9 +327,11 @@ static void *attempt_thread(void *data)
|
|||
if (!ast_strlen_zero(o->app)) {
|
||||
ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
|
||||
res = ast_pbx_outgoing_app(o->tech, o->format, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
|
||||
o->vars = NULL;
|
||||
} else {
|
||||
ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
|
||||
res = ast_pbx_outgoing_exten(o->tech, o->format, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
|
||||
o->vars = NULL;
|
||||
}
|
||||
if (res) {
|
||||
ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason));
|
||||
|
|
|
@ -249,6 +249,23 @@ static int handle_stopplaytones(struct ast_channel *chan, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* helper function to delete a tone_zone in its entirety */
|
||||
static inline void free_zone(struct ind_tone_zone* zone)
|
||||
{
|
||||
while (zone->tones) {
|
||||
struct ind_tone_zone_sound *tmp = zone->tones->next;
|
||||
ast_free((void *)zone->tones->name);
|
||||
ast_free((void *)zone->tones->data);
|
||||
ast_free(zone->tones);
|
||||
zone->tones = tmp;
|
||||
}
|
||||
|
||||
if (zone->ringcadence)
|
||||
ast_free(zone->ringcadence);
|
||||
|
||||
ast_free(zone);
|
||||
}
|
||||
|
||||
/*! \brief load indications module */
|
||||
static int ind_load_module(int reload)
|
||||
{
|
||||
|
@ -303,6 +320,7 @@ static int ind_load_module(int reload)
|
|||
}
|
||||
if (!(tmp = ast_realloc(tones->ringcadence, (tones->nrringcadence + 1) * sizeof(int)))) {
|
||||
ast_config_destroy(cfg);
|
||||
free_zone(tones);
|
||||
return -1;
|
||||
}
|
||||
tones->ringcadence = tmp;
|
||||
|
@ -319,13 +337,14 @@ static int ind_load_module(int reload)
|
|||
struct ind_tone_zone* azone;
|
||||
if (!(azone = ast_calloc(1, sizeof(*azone)))) {
|
||||
ast_config_destroy(cfg);
|
||||
free_zone(tones);
|
||||
return -1;
|
||||
}
|
||||
ast_copy_string(azone->country, country, sizeof(azone->country));
|
||||
ast_copy_string(azone->alias, cxt, sizeof(azone->alias));
|
||||
if (ast_register_indication_country(azone)) {
|
||||
ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno);
|
||||
ast_free(tones);
|
||||
free_zone(tones);
|
||||
}
|
||||
/* next item */
|
||||
country = strsep(&c,",");
|
||||
|
@ -358,17 +377,20 @@ out: v = v->next;
|
|||
if (tones->description[0] || tones->alias[0] || tones->tones) {
|
||||
if (ast_register_indication_country(tones)) {
|
||||
ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
|
||||
ast_free(tones);
|
||||
free_zone(tones);
|
||||
}
|
||||
} else ast_free(tones);
|
||||
} else {
|
||||
free_zone(tones);
|
||||
}
|
||||
|
||||
cxt = ast_category_browse(cfg, cxt);
|
||||
}
|
||||
|
||||
/* determine which country is the default */
|
||||
country = ast_variable_retrieve(cfg,"general","country");
|
||||
if (!country || !*country || ast_set_indication_country(country))
|
||||
if (ast_strlen_zero(country) || ast_set_indication_country(country)) {
|
||||
ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n");
|
||||
}
|
||||
|
||||
ast_config_destroy(cfg);
|
||||
return 0;
|
||||
|
|
Reference in New Issue