Index: res/res_config_sqlite.c =================================================================== --- res/res_config_sqlite.c (revision 131914) +++ res/res_config_sqlite.c (working copy) @@ -129,19 +129,26 @@ /*! * Maximum number of loops before giving up executing a query. Calls to - * sqlite_xxx() functions which can return SQLITE_BUSY or SQLITE_LOCKED - * are enclosed by RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g. + * sqlite_xxx() functions which can return SQLITE_BUSY are enclosed by + * RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g. *
- * char *errormsg;
+ * char *errormsg = NULL;
  * int error;
  *
  * RES_CONFIG_SQLITE_BEGIN
  *	 error = sqlite_exec(db, query, NULL, NULL, &errormsg);
- * RES_CONFIG_SQLITE_END(error)
+ * RES_CONFIG_SQLITE_END(error, errormsg)
  *
  * if (error)
  *	 ...;
+ *
+ * sqlite_freemem(errormsg);
+ * errormsg = NULL;
  * 
+ * + * Note that RES_CONFIG_SQLITE_END(error, NULL) will NOT work because NULL + * is not an lvalue. If &errormsg is replaced by NULL in the SQLite function + * call, a new variant of RES_CONFIG_SQLITE_END will have to be written. */ #define RES_CONFIG_SQLITE_MAX_LOOPS 10 @@ -152,23 +159,42 @@ */ #define RES_CONFIG_SQLITE_BEGIN \ MACRO_BEGIN \ - int __i; \ + int __i = 0; \ \ - for (__i = 0; __i < RES_CONFIG_SQLITE_MAX_LOOPS; __i++) { + while (1) { /*! * Macro used after executing a query. * * \see RES_CONFIG_SQLITE_MAX_LOOPS. */ -#define RES_CONFIG_SQLITE_END(error) \ - if (error != SQLITE_BUSY && error != SQLITE_LOCKED) \ +#define RES_CONFIG_SQLITE_END(error, errormsg) \ + if (error != SQLITE_BUSY) \ break; \ usleep(1000); \ + if (++__i >= RES_CONFIG_SQLITE_MAX_LOOPS) \ + break; \ + if (errormsg) { \ + sqlite_freemem(errormsg); \ + errormsg = NULL; \ + } \ } \ MACRO_END; /*! + * Macro that simply returns errormsg if available (not NULL) or else + * returns a static string description of the error code. + * This macro is useful when an SQLite error message is to be logged + * somewhere, because SQLite can't give us any hard warranty that the + * allocation of the errormsg will succeed, and if it fails errormsg + * will remain NULL despite error being set. + * However, errormsg is sometimes more precise so in the general case + * it is what we want to log. + */ +#define RES_CONFIG_SQLITE_ERRORMSG(errormsg, error) \ + ((errormsg) ? (errormsg) : sqlite_error_string(error)) + +/*! * Structure sent to the SQLite callback function for static configuration. * * \see add_cfg_entry() @@ -657,7 +683,7 @@ static int cdr_handler(struct ast_cdr *cdr) { - char *query, *errormsg; + char *query, *errormsg = NULL; int error; query = sqlite_mprintf(sql_add_cdr_entry, cdr_table, cdr->clid, @@ -679,18 +705,19 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) ast_mutex_unlock(&mutex); sqlite_freemem(query); if (error) { - ast_log(LOG_ERROR, "%s\n", errormsg); + ast_log(LOG_ERROR, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); return 1; } + sqlite_freemem(errormsg); return 0; } @@ -757,7 +784,7 @@ struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked) { struct cfg_entry_args args; - char *query, *errormsg; + char *query, *errormsg = NULL; int error; if (!config_table) { @@ -786,7 +813,7 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, add_cfg_entry, &args, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) ast_mutex_unlock(&mutex); @@ -794,11 +821,12 @@ sqlite_freemem(query); if (error) { - ast_log(LOG_ERROR, "%s\n", errormsg); + ast_log(LOG_ERROR, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); return NULL; } + sqlite_freemem(errormsg); return cfg; } @@ -871,7 +899,7 @@ static struct ast_variable * realtime_handler(const char *database, const char *table, va_list ap) { - char *query, *errormsg, *op, *tmp_str; + char *query, *errormsg = NULL, *op, *tmp_str; struct rt_cfg_entry_args args; const char **params, **vals; size_t params_count; @@ -942,19 +970,20 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, add_rt_cfg_entry, &args, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) ast_mutex_unlock(&mutex); sqlite_freemem(query); if (error) { - ast_log(LOG_WARNING, "%s\n", errormsg); + ast_log(LOG_WARNING, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); ast_variables_destroy(args.var); return NULL; } + sqlite_freemem(errormsg); return args.var; } @@ -1009,7 +1038,7 @@ static struct ast_config *realtime_multi_handler(const char *database, const char *table, va_list ap) { - char *query, *errormsg, *op, *tmp_str, *initfield; + char *query, *errormsg = NULL, *op, *tmp_str, *initfield; struct rt_multi_cfg_entry_args args; const char **params, **vals; struct ast_config *cfg; @@ -1107,7 +1136,7 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, add_rt_multi_cfg_entry, &args, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) ast_mutex_unlock(&mutex); @@ -1115,19 +1144,20 @@ ast_free(initfield); if (error) { - ast_log(LOG_WARNING, "%s\n", errormsg); + ast_log(LOG_WARNING, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); ast_config_destroy(cfg); return NULL; } + sqlite_freemem(errormsg); return cfg; } static int realtime_update_handler(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap) { - char *query, *errormsg, *tmp_str; + char *query, *errormsg = NULL, *tmp_str; const char **params, **vals; size_t params_count; int error, rows_num; @@ -1187,7 +1217,7 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) if (!error) rows_num = sqlite_changes(db); @@ -1199,16 +1229,16 @@ sqlite_freemem(query); if (error) { - ast_log(LOG_WARNING, "%s\n", errormsg); - sqlite_freemem(errormsg); + ast_log(LOG_WARNING, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); } + sqlite_freemem(errormsg); return rows_num; } static int realtime_store_handler(const char *database, const char *table, va_list ap) { - char *errormsg, *tmp_str, *tmp_keys = NULL, *tmp_keys2 = NULL, *tmp_vals = NULL, *tmp_vals2 = NULL; + char *errormsg = NULL, *tmp_str, *tmp_keys = NULL, *tmp_keys2 = NULL, *tmp_vals = NULL, *tmp_vals2 = NULL; const char **params, **vals; size_t params_count; int error, rows_id; @@ -1280,7 +1310,7 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) if (!error) { rows_id = sqlite_last_insert_rowid(db); @@ -1293,17 +1323,17 @@ sqlite_freemem(tmp_str); if (error) { - ast_log(LOG_WARNING, "%s\n", errormsg); - sqlite_freemem(errormsg); + ast_log(LOG_WARNING, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); } + sqlite_freemem(errormsg); return rows_id; } static int realtime_destroy_handler(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap) { - char *query, *errormsg, *tmp_str; + char *query, *errormsg = NULL, *tmp_str; const char **params, **vals; size_t params_count; int error, rows_num; @@ -1358,7 +1388,7 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) if (!error) rows_num = sqlite_changes(db); @@ -1370,10 +1400,10 @@ sqlite_freemem(query); if (error) { - ast_log(LOG_WARNING, "%s\n", errormsg); - sqlite_freemem(errormsg); + ast_log(LOG_WARNING, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); } + sqlite_freemem(errormsg); return rows_num; } @@ -1431,7 +1461,7 @@ static int load_module(void) { - char *errormsg; + char *errormsg = NULL; int error; db = NULL; @@ -1446,11 +1476,13 @@ return AST_MODULE_LOAD_DECLINE; if (!(db = sqlite_open(dbfile, 0660, &errormsg))) { - ast_log(LOG_ERROR, "%s\n", errormsg); + ast_log(LOG_ERROR, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); unload_module(); return 1; } + sqlite_freemem(errormsg); + errormsg = NULL; ast_config_engine_register(&sqlite_engine); @@ -1474,7 +1506,7 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) sqlite_freemem(query); @@ -1483,13 +1515,14 @@ * Unexpected error. */ if (error != SQLITE_ERROR) { - ast_log(LOG_ERROR, "%s\n", errormsg); + ast_log(LOG_ERROR, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); unload_module(); return 1; } + sqlite_freemem(errormsg); + errormsg = NULL; - sqlite_freemem(errormsg); query = sqlite_mprintf(sql_create_cdr_table, cdr_table); if (!query) { @@ -1502,18 +1535,21 @@ RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_CONFIG_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error, errormsg) sqlite_freemem(query); if (error) { - ast_log(LOG_ERROR, "%s\n", errormsg); + ast_log(LOG_ERROR, "%s\n", RES_CONFIG_SQLITE_ERRORMSG(errormsg, error)); sqlite_freemem(errormsg); unload_module(); return 1; } } + sqlite_freemem(errormsg); + errormsg = NULL; + error = ast_cdr_register(RES_CONFIG_SQLITE_NAME, RES_CONFIG_SQLITE_DESCRIPTION, cdr_handler); if (error) {