Newer
Older
/* auto rotate if sig SIGXFSZ comes a-knockin */
(void) signal(SIGXFSZ, (void *) handle_SIGXFSZ);
/* start logger thread */
ast_cond_init(&logcond, NULL);
if (ast_pthread_create(&logthread, NULL, logger_thread, NULL) < 0) {
ast_cond_destroy(&logcond);
return -1;
}
/* register the logger cli commands */
ast_cli_register_multiple(cli_logger, sizeof(cli_logger) / sizeof(struct ast_cli_entry));
Tilghman Lesher
committed
ast_mkdir(ast_config_AST_LOG_DIR, 0777);
Joshua Colp
committed
init_logger_chain(0 /* locked */);
/* create the eventlog */
if (logfiles.event_log) {
snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, EVENTLOG);
eventlog = fopen(tmp, "a");
if (eventlog) {
ast_log(LOG_EVENT, "Started Asterisk Event Logger\n");
ast_verb(1, "Asterisk Event Logger Started %s\n", tmp);
ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, queue_log_name);
qlog = fopen(tmp, "a");
ast_queue_log("NONE", "NONE", "NONE", "QUEUESTART", "%s", "");
}
return res;
void close_logger(void)
{
struct logchannel *f = NULL;
/* Stop logger thread */
AST_LIST_LOCK(&logmsgs);
close_logger_thread = 1;
ast_cond_signal(&logcond);
AST_LIST_UNLOCK(&logmsgs);
if (logthread != AST_PTHREADT_NULL)
pthread_join(logthread, NULL);
AST_RWLIST_WRLOCK(&logchannels);
if (eventlog) {
fclose(eventlog);
eventlog = NULL;
}
if (qlog) {
fclose(qlog);
qlog = NULL;
}
AST_RWLIST_TRAVERSE(&logchannels, f, list) {
if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
fclose(f->fileptr);
f->fileptr = NULL;
closelog(); /* syslog */
AST_RWLIST_UNLOCK(&logchannels);
return;
}
/*!
* \brief send log messages to syslog and/or the console
*/
void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
struct logmsg *logmsg = NULL;
struct ast_str *buf = NULL;
Tilghman Lesher
committed
struct ast_tm tm;
struct timeval tv = ast_tvnow();
int res = 0;
if (!(buf = ast_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE)))
if (AST_RWLIST_EMPTY(&logchannels)) {
Steve Murphy
committed
/*
* we don't have the logger chain configured yet,
* so just log to stdout
*/
Steve Murphy
committed
if (level != __LOG_VERBOSE) {
int res;
va_start(ap, fmt);
res = ast_str_set_va(&buf, BUFSIZ, fmt, ap); /* XXX BUFSIZ ? */
Steve Murphy
committed
va_end(ap);
if (res != AST_DYNSTR_BUILD_FAILED) {
term_filter_escapes(buf->str);
Steve Murphy
committed
fputs(buf->str, stdout);
Steve Murphy
committed
}
return;
}
/* don't display LOG_DEBUG messages unless option_verbose _or_ option_debug
are non-zero; LOG_DEBUG messages can still be displayed if option_debug
is zero, if option_verbose is non-zero (this allows for 'level zero'
LOG_DEBUG messages to be displayed, if the logmask on any channel
allows it)
*/
if (!option_verbose && !option_debug && (level == __LOG_DEBUG))
Kevin P. Fleming
committed
/* Ignore anything that never gets logged anywhere */
if (!(global_logmask & (1 << level)))
return;
/* Build string */
va_start(ap, fmt);
res = ast_str_set_va(&buf, BUFSIZ, fmt, ap);
va_end(ap);
Jeremy McNamara
committed
/* If the build failed, then abort and free this structure */
if (res == AST_DYNSTR_BUILD_FAILED)
return;
/* Create a new logging message */
if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1)))
Russell Bryant
committed
/* Copy string over */
strcpy(logmsg->str, buf->str);
/* Set type to be normal */
logmsg->type = LOGMSG_NORMAL;
/* Create our date/time */
Tilghman Lesher
committed
ast_localtime(&tv, &tm, NULL);
ast_strftime(logmsg->date, sizeof(logmsg->date), dateformat, &tm);
/* Copy over data */
logmsg->level = level;
logmsg->line = line;
Russell Bryant
committed
ast_copy_string(logmsg->file, file, sizeof(logmsg->file));
ast_copy_string(logmsg->function, function, sizeof(logmsg->function));
/* If the logger thread is active, append it to the tail end of the list - otherwise skip that step */
if (logthread != AST_PTHREADT_NULL) {
AST_LIST_LOCK(&logmsgs);
AST_LIST_INSERT_TAIL(&logmsgs, logmsg, list);
ast_cond_signal(&logcond);
AST_LIST_UNLOCK(&logmsgs);
} else {
logger_print_normal(logmsg);
Tilghman Lesher
committed
ast_free(logmsg);
return;
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
#ifdef HAVE_BKTR
struct ast_bt *ast_bt_create(void)
{
struct ast_bt *bt = ast_calloc(1, sizeof(*bt));
if (!bt) {
ast_log(LOG_ERROR, "Unable to allocate memory for backtrace structure!\n");
return NULL;
}
bt->alloced = 1;
ast_bt_get_addresses(bt);
return bt;
}
int ast_bt_get_addresses(struct ast_bt *bt)
{
bt->num_frames = backtrace(bt->addresses, AST_MAX_BT_FRAMES);
return 0;
}
void *ast_bt_destroy(struct ast_bt *bt)
{
if (bt->alloced) {
ast_free(bt);
}
return NULL;
}
#endif /* HAVE_BKTR */
Tilghman Lesher
committed
#ifdef HAVE_BKTR
struct ast_bt *backtrace;
int i = 0;
if (!(backtrace = ast_bt_create())) {
ast_log(LOG_WARNING, "Unable to allocate space for backtrace structure\n");
return;
}
if ((strings = backtrace_symbols(backtrace->addresses, backtrace->num_frames))) {
ast_debug(1, "Got %d backtrace record%c\n", backtrace->num_frames, backtrace->num_frames != 1 ? 's' : ' ');
for (i = 0; i < backtrace->num_frames; i++) {
ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)backtrace->addresses[i], strings[i]);
ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)backtrace->addresses[i], strings[i]);
free(strings);
} else {
ast_debug(1, "Could not allocate memory for backtrace\n");
ast_bt_destroy(backtrace);
Tilghman Lesher
committed
ast_log(LOG_WARNING, "Must run configure with '--with-execinfo' for stack backtraces.\n");
Mark Michelson
committed
void __ast_verbose(const char *file, int line, const char *func, const char *fmt, ...)
struct logmsg *logmsg = NULL;
struct ast_str *buf = NULL;
int res = 0;
if (!(buf = ast_str_thread_get(&verbose_buf, VERBOSE_BUF_INIT_SIZE)))
return;
if (ast_opt_timestamp) {
struct timeval tv;
struct ast_tm tm;
char date[40];
char *datefmt;
ast_localtime(&tv, &tm, NULL);
ast_strftime(date, sizeof(date), dateformat, &tm);
datefmt = alloca(strlen(date) + 3 + strlen(fmt) + 1);
sprintf(datefmt, "%c[%s] %s", 127, date, fmt);
} else {
char *tmp = alloca(strlen(fmt) + 2);
sprintf(tmp, "%c%s", 127, fmt);
fmt = tmp;
/* Build string */
va_start(ap, fmt);
res = ast_str_set_va(&buf, 0, fmt, ap);
va_end(ap);
/* If the build failed then we can drop this allocated message */
if (res == AST_DYNSTR_BUILD_FAILED)
return;
if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1)))
return;
strcpy(logmsg->str, buf->str);
Mark Michelson
committed
ast_log(__LOG_VERBOSE, file, line, func, "%s", logmsg->str + 1);
Joshua Colp
committed
/* Set type */
logmsg->type = LOGMSG_VERBOSE;
/* Add to the list and poke the thread if possible */
if (logthread != AST_PTHREADT_NULL) {
AST_LIST_LOCK(&logmsgs);
AST_LIST_INSERT_TAIL(&logmsgs, logmsg, list);
ast_cond_signal(&logcond);
AST_LIST_UNLOCK(&logmsgs);
} else {
logger_print_verbose(logmsg);
Tilghman Lesher
committed
ast_free(logmsg);
}
int ast_register_verbose(void (*v)(const char *string))
{
struct verb *verb;
if (!(verb = ast_malloc(sizeof(*verb))))
return -1;
AST_RWLIST_WRLOCK(&verbosers);
AST_RWLIST_INSERT_HEAD(&verbosers, verb, list);
AST_RWLIST_UNLOCK(&verbosers);
int ast_unregister_verbose(void (*v)(const char *string))
AST_RWLIST_WRLOCK(&verbosers);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&verbosers, cur, list) {
if (cur->verboser == v) {
AST_RWLIST_REMOVE_CURRENT(list);
Tilghman Lesher
committed
ast_free(cur);
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&verbosers);
return cur ? 0 : -1;