Since we construct our error/debug messages via multiple calls to stdio primitives, we are at risk of multiple threads interleaving their output if they try to output at once. Add a mutex to group related outputs into an atomic chunk. Signed-off-by: Eric Blake <eblake@redhat.com> --- src/errors.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/errors.c b/src/errors.c index 5f14315..2fc83ab 100644 --- a/src/errors.c +++ b/src/errors.c @@ -1,5 +1,5 @@ /* nbdkit - * Copyright (C) 2013 Red Hat Inc. + * Copyright (C) 2013-2017 Red Hat Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,10 +38,30 @@ #include <stdarg.h> #include <string.h> #include <errno.h> +#include <assert.h> +#include <pthread.h> #include "nbdkit-plugin.h" #include "internal.h" +/* Used to group piecemeal message construction into atomic output. */ +static pthread_mutex_t errors_lock = PTHREAD_MUTEX_INITIALIZER; + +static void +lock (void) +{ + int r = pthread_mutex_lock(&errors_lock); + assert(!r); +} + +static void +unlock (void) +{ + int r = pthread_mutex_unlock(&errors_lock); + assert(!r); +} + +/* Called with lock taken. */ static void prologue (const char *type) { @@ -69,11 +89,13 @@ nbdkit_vdebug (const char *fs, va_list args) if (!verbose) return; + lock (); prologue ("debug"); vfprintf (stderr, fs, args); fprintf (stderr, "\n"); + unlock (); errno = err; } @@ -88,6 +110,7 @@ nbdkit_debug (const char *fs, ...) if (!verbose) return; + lock (); prologue ("debug"); va_start (args, fs); @@ -95,6 +118,7 @@ nbdkit_debug (const char *fs, ...) va_end (args); fprintf (stderr, "\n"); + unlock (); errno = err; } @@ -105,11 +129,13 @@ nbdkit_verror (const char *fs, va_list args) { int err = errno; + lock (); prologue ("error"); vfprintf (stderr, fs, args); fprintf (stderr, "\n"); + unlock (); errno = err; } @@ -121,6 +147,7 @@ nbdkit_error (const char *fs, ...) va_list args; int err = errno; + lock (); prologue ("error"); va_start (args, fs); @@ -128,6 +155,7 @@ nbdkit_error (const char *fs, ...) va_end (args); fprintf (stderr, "\n"); + unlock (); errno = err; } -- 2.13.6