[Intel-gfx] [PATCH i-g-t 1/5] lib: print recent log output if a test fails
Thomas Wood
thomas.wood at intel.com
Wed Dec 17 10:10:46 PST 2014
On 17 December 2014 at 17:19, Chris Wilson <chris at chris-wilson.co.uk> wrote:
> On Wed, Dec 17, 2014 at 04:45:43PM +0000, Thomas Wood wrote:
>> Print recent log entries if a test or subtest fails and the current log
>> level is set to info.
>>
>> v2: Write log to stderr after test or subtest failure and make log
>> buffering thread safe.
>>
>> Signed-off-by: Thomas Wood <thomas.wood at intel.com>
>> ---
>> lib/igt_core.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
>> 1 file changed, 96 insertions(+), 7 deletions(-)
>>
>> diff --git a/lib/igt_core.c b/lib/igt_core.c
>> index 08e0c47..457b3b1 100644
>> --- a/lib/igt_core.c
>> +++ b/lib/igt_core.c
>> @@ -50,6 +50,8 @@
>> #include <termios.h>
>> #include <errno.h>
>> #include <time.h>
>> +#include <limits.h>
>> +#include <pthread.h>
>>
>> #include "drmtest.h"
>> #include "intel_chipset.h"
>> @@ -228,8 +230,18 @@ enum {
>> OPT_HELP = 'h'
>> };
>>
>> +static const char *command_str;
>> +static int igt_exitcode = IGT_EXIT_SUCCESS;
>> +
>> static char* igt_log_domain_filter;
>>
>> +static struct {
>> + char *entries[256];
>> + uint8_t start, end;
>> +} log_buffer;
>> +static pthread_mutex_t log_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
>> +
>> +
>> __attribute__((format(printf, 1, 2)))
>> static void kmsg(const char *format, ...)
>> #define KERN_EMER "<0>"
>> @@ -353,6 +365,52 @@ static void low_mem_killer_disable(bool disable)
>> chmod(adj_fname, buf.st_mode);
>> }
>>
>> +#define write_log_msg(x) write(STDERR_FILENO, x, strlen(x))
>> +
>> +/* this function must be safe to be called inside a signal handler */
>> +static void write_log(void)
>> +{
>> + uint8_t i;
>> + char *last_line;
>> +
>> + pthread_mutex_lock(&log_buffer_mutex);
>> +
>> + /* don't write an empty log */
>> + if (log_buffer.start == log_buffer.end) {
>> + pthread_mutex_unlock(&log_buffer_mutex);
>> + return;
>> + }
>> +
>> + if (in_subtest) {
>> + write_log_msg("--- Subtest ");
>> + write_log_msg(in_subtest);
>> + } else {
>> + write_log_msg("--- Test ");
>> + write_log_msg(command_str);
>> + }
>> + write_log_msg(" failed.\n");
>> + write_log_msg("--- Log Start\n");
>> +
>> + i = log_buffer.start;
>> + do {
>> + last_line = log_buffer.entries[i];
>> + write_log_msg(last_line);
>
> What happens if nothing is in the log:
> log_buffer.start == log_buffer.end == 0
>
> last_line[pos] is a *NULL, as may strlen(NULL).
>
> When something is in the log, start != end, so this can just be a simple
>
> if (log_buffer.start == log_buffer.end)
> return;
Yes, this check is done at the start of the function.
>
> i = log_buffer.start;
> do {
>> +
>> + /* ensure each line ends in a newline */
>> + for (int pos = 0; last_line[pos] != '\0'; pos++) {
>> + if (last_line[pos] != '\n'
>> + && last_line[pos + 1] == '\0')
>> + write_log_msg("\n");
>> + }
>
> pos = strlen(last_line);
> if (pos > 0 && last_line[pos-1] != '\n')
> write_log_msg("\n");
The for loop above was to avoid using strlen (which is not listed as
signal safe), but strlen is being used in write_log_msg, so this would
need further work to make it safe too.
>
> if (i == log_buffer.end)
> break;
>
> i++;
> } while (1);
>
> It's not the neatest of loops, but it should be effective.
>
>> + i++;
>> + } while (i != log_buffer.start && i != log_buffer.end);
>> +
>> + write_log_msg("--- Log End\n");
>
> After it has dumped the log, do you want to reset the log_buffer?
> i.e. log_buffer.start = log_buffer.end;
Yes, this is added in patch 4 of this series.
>
>> + pthread_mutex_unlock(&log_buffer_mutex);
>
> I was worried by taking locks inside a signal handler, but this looks
> like it could be made safe, and with a bit more work, you can make the
> other half robust as well:
Yes, this is problematic. It will probably be worth adding some
library test cases to try and ensure the default signal handlers are
as safe as possible.
>
> char *new, *old;
>
> asprintf(&new,
> "(%s:%d) %s%s%s: %s",
> program_name, getpid(),
> (domain) ? domain : "",
> (domain) ? "-" : "",
> igt_log_level_str[level],
> line);
>
> pthread_mutex_lock(&log_buffer_mutex);
> old = log_buffer.entries[log_buffer.end];
> log_bufffer.entries[log_buffer.end] = new;
> if (++log_buffer.end == log_buffer.start)
> log_buffer.start++;
> pthread_mutex_unlock(&log_buffer_mutex);
>
> free(old);
>
> i.e. only do the pointer head/tail assignment inside the lock to
> minimise exposure.
> -Chris
>
> --
> Chris Wilson, Intel Open Source Technology Centre
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list