X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fhelper%2Flog.c;h=caa0a66bf64707b2d94d3519d489d9687fa328b9;hb=f735faa9319af324b94e4257444419c8dfec6592;hp=8f48b928b5640791b1fd757be7d1150bdb24a742;hpb=deff24afa13fe5188c207258d6d1935bc3dd0870;p=fw%2Fopenocd diff --git a/src/helper/log.c b/src/helper/log.c index 8f48b928b..caa0a66bf 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -28,6 +28,7 @@ #include "log.h" #include "command.h" +#include "replacements.h" #include "time_support.h" #include @@ -40,7 +41,7 @@ #endif #endif -int debug_level = -1; +int debug_level = LOG_LVL_INFO; static FILE *log_output; static struct log_callback *log_callbacks; @@ -91,6 +92,14 @@ static void log_puts(enum log_levels level, const char *string) { char *f; + + if (!log_output) { + /* log_init() not called yet; print on stderr */ + fputs(string, stderr); + fflush(stderr); + return; + } + if (level == LOG_LVL_OUTPUT) { /* do not prepend any headers, just print out what we were given and return */ fputs(string, log_output); @@ -99,7 +108,7 @@ static void log_puts(enum log_levels level, } f = strrchr(file, '/'); - if (f != NULL) + if (f) file = f + 1; if (strlen(string) > 0) { @@ -154,7 +163,7 @@ void log_printf(enum log_levels level, va_start(ap, format); string = alloc_vprintf(format, ap); - if (string != NULL) { + if (string) { log_puts(level, file, line, function, string); free(string); } @@ -220,20 +229,31 @@ COMMAND_HANDLER(handle_debug_level_command) COMMAND_HANDLER(handle_log_output_command) { + if (CMD_ARGC == 0 || (CMD_ARGC == 1 && strcmp(CMD_ARGV[0], "default") == 0)) { + if (log_output != stderr && log_output) { + /* Close previous log file, if it was open and wasn't stderr. */ + fclose(log_output); + } + log_output = stderr; + LOG_DEBUG("set log_output to default"); + return ERROR_OK; + } if (CMD_ARGC == 1) { FILE *file = fopen(CMD_ARGV[0], "w"); - if (file == NULL) { + if (!file) { LOG_ERROR("failed to open output log '%s'", CMD_ARGV[0]); return ERROR_FAIL; } - if (log_output != stderr && log_output != NULL) { + if (log_output != stderr && log_output) { /* Close previous log file, if it was open and wasn't stderr. */ fclose(log_output); } log_output = file; + LOG_DEBUG("set log_output to \"%s\"", CMD_ARGV[0]); + return ERROR_OK; } - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } static const struct command_registration log_command_handlers[] = { @@ -242,7 +262,7 @@ static const struct command_registration log_command_handlers[] = { .handler = handle_log_output_command, .mode = COMMAND_ANY, .help = "redirect logging to a file (default: stderr)", - .usage = "file_name", + .usage = "[file_name | \"default\"]", }, { .name = "debug_level", @@ -266,20 +286,17 @@ void log_init(void) { /* set defaults for daemon configuration, * if not set by cmdline or cfgfile */ - if (debug_level == -1) - debug_level = LOG_LVL_INFO; - char *debug_env = getenv("OPENOCD_DEBUG_LEVEL"); - if (NULL != debug_env) { + if (debug_env) { int value; int retval = parse_int(debug_env, &value); - if (ERROR_OK == retval && + if (retval == ERROR_OK && debug_level >= LOG_LVL_SILENT && debug_level <= LOG_LVL_DEBUG_IO) debug_level = value; } - if (log_output == NULL) + if (!log_output) log_output = stderr; start = last_time = timeval_ms(); @@ -305,7 +322,7 @@ int log_add_callback(log_callback_fn fn, void *priv) /* alloc memory, it is safe just to return in case of an error, no need for the caller to *check this */ cb = malloc(sizeof(struct log_callback)); - if (cb == NULL) + if (!cb) return ERROR_BUF_TOO_SMALL; /* add item to the beginning of the linked list */ @@ -350,7 +367,7 @@ char *alloc_vprintf(const char *fmt, va_list ap) * other code depend on that. They should be probably be fixed, but for * now reserve the extra byte. */ string = malloc(len + 2); - if (string == NULL) + if (!string) return NULL; /* do the real work */ @@ -390,25 +407,43 @@ char *alloc_printf(const char *format, ...) * fast when invoked more often than every 500ms. * */ -void keep_alive() +#define KEEP_ALIVE_KICK_TIME_MS 500 +#define KEEP_ALIVE_TIMEOUT_MS 1000 + +static void gdb_timeout_warning(int64_t delta_time) +{ + extern int gdb_actual_connections; + + if (gdb_actual_connections) + LOG_WARNING("keep_alive() was not invoked in the " + "%d ms timelimit. GDB alive packet not " + "sent! (%" PRId64 " ms). Workaround: increase " + "\"set remotetimeout\" in GDB", + KEEP_ALIVE_TIMEOUT_MS, + delta_time); + else + LOG_DEBUG("keep_alive() was not invoked in the " + "%d ms timelimit (%" PRId64 " ms). This may cause " + "trouble with GDB connections.", + KEEP_ALIVE_TIMEOUT_MS, + delta_time); +} + +void keep_alive(void) { current_time = timeval_ms(); - if (current_time-last_time > 1000) { - extern int gdb_actual_connections; - - if (gdb_actual_connections) - LOG_WARNING("keep_alive() was not invoked in the " - "1000ms timelimit. GDB alive packet not " - "sent! (%" PRId64 "). Workaround: increase " - "\"set remotetimeout\" in GDB", - current_time-last_time); - else - LOG_DEBUG("keep_alive() was not invoked in the " - "1000ms timelimit (%" PRId64 "). This may cause " - "trouble with GDB connections.", - current_time-last_time); + + int64_t delta_time = current_time - last_time; + + if (delta_time > KEEP_ALIVE_TIMEOUT_MS) { + last_time = current_time; + + gdb_timeout_warning(delta_time); } - if (current_time-last_time > 500) { + + if (delta_time > KEEP_ALIVE_KICK_TIME_MS) { + last_time = current_time; + /* this will keep the GDB connection alive */ LOG_USER_N("%s", ""); @@ -419,26 +454,30 @@ void keep_alive() * * These functions should be invoked at a well defined spot in server.c */ - - last_time = current_time; } } /* reset keep alive timer without sending message */ -void kept_alive() +void kept_alive(void) { current_time = timeval_ms(); + + int64_t delta_time = current_time - last_time; + last_time = current_time; + + if (delta_time > KEEP_ALIVE_TIMEOUT_MS) + gdb_timeout_warning(delta_time); } -/* if we sleep for extended periods of time, we must invoke keep_alive() intermittantly */ +/* if we sleep for extended periods of time, we must invoke keep_alive() intermittently */ void alive_sleep(uint64_t ms) { - uint64_t napTime = 10; - for (uint64_t i = 0; i < ms; i += napTime) { + uint64_t nap_time = 10; + for (uint64_t i = 0; i < ms; i += nap_time) { uint64_t sleep_a_bit = ms - i; - if (sleep_a_bit > napTime) - sleep_a_bit = napTime; + if (sleep_a_bit > nap_time) + sleep_a_bit = nap_time; usleep(sleep_a_bit * 1000); keep_alive(); @@ -455,7 +494,7 @@ void busy_sleep(uint64_t ms) } } -/* Maximum size of socket error message retreived from operation system */ +/* Maximum size of socket error message retrieved from operation system */ #define MAX_SOCKET_ERR_MSG_LENGTH 256 /* Provide log message for the last socket error. @@ -479,3 +518,16 @@ void log_socket_error(const char *socket_desc) LOG_ERROR("Error on socket '%s': errno==%d, message: %s.", socket_desc, error_code, strerror(error_code)); #endif } + +/** + * Find the first non-printable character in the char buffer, return a pointer to it. + * If no such character exists, return NULL. + */ +char *find_nonprint_char(char *buf, unsigned buf_len) +{ + for (unsigned int i = 0; i < buf_len; i++) { + if (!isprint(buf[i])) + return buf + i; + } + return NULL; +}