nbdkit/0012-server-Make-debug-mess...

158 lines
3.7 KiB
Diff

From 453a7611b625fc6f306a47ccc61bf3b83d75e522 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 5 Aug 2021 10:13:53 +0100
Subject: [PATCH] server: Make debug messages atomic
Previously we used flockfile around the separate fprintf statements
used to emit debug messages. However this does not make debug
messages atomic (only atomic with respect to other nbdkit threads).
It's easy to see this in strace:
1915655 write(2, "nbdkit: ", 8) = 8
1915655 write(2, "debug: ", 7) = 7
1915655 write(2, "nbdkit 1.27.3 (nbdkit-1.27.3-1.f"..., 36) = 36
1915655 write(2, "\n", 1) = 1
We require open_memstream already, so use this to print messages to a
string buffer which we can emit in a single write.
This fixes various tests which grep the log file looking for sentinel
messages. In particular a recent Fedora build failure in
test-nbdkit-backend-debug.sh was caused by this, but there are other
tests that fail occasionally for the same reason.
This change also tries harder to set errno correctly before expanding
the format string (for debug messages that contain %m).
Note that libnbd already emits atomic messages.
(cherry picked from commit 30eef3bf2d93b12072f91f95987bae33f9e3fe1a)
---
server/debug.c | 72 ++++++++++++++++++++++++++++++++------------------
1 file changed, 46 insertions(+), 26 deletions(-)
diff --git a/server/debug.c b/server/debug.c
index eede5e16..07710581 100644
--- a/server/debug.c
+++ b/server/debug.c
@@ -40,23 +40,22 @@
#include "internal.h"
-/* Called with flockfile (stderr) taken. */
static void
-prologue (void)
+prologue (FILE *fp)
{
const char *name = threadlocal_get_name ();
size_t instance_num = threadlocal_get_instance_num ();
- fprintf (stderr, "%s: ", program_name);
+ fprintf (fp, "%s: ", program_name);
if (name) {
- fprintf (stderr, "%s", name);
+ fprintf (fp, "%s", name);
if (instance_num > 0)
- fprintf (stderr, "[%zu]", instance_num);
- fprintf (stderr, ": ");
+ fprintf (fp, "[%zu]", instance_num);
+ fprintf (fp, ": ");
}
- fprintf (stderr, "debug: ");
+ fprintf (fp, "debug: ");
}
/* Note: preserves the previous value of errno. */
@@ -64,20 +63,30 @@ NBDKIT_DLL_PUBLIC void
nbdkit_vdebug (const char *fs, va_list args)
{
int err = errno;
+ CLEANUP_FREE char *str = NULL;
+ size_t len = 0;
+ FILE *fp;
if (!verbose)
return;
-#ifdef HAVE_FLOCKFILE
- flockfile (stderr);
-#endif
- prologue ();
- vfprintf (stderr, fs, args);
+ fp = open_memstream (&str, &len);
+ if (fp == NULL) {
+ /* Try to emit what we can. */
+ errno = err;
+ vfprintf (stderr, fs, args);
+ return;
+ }
- fprintf (stderr, "\n");
-#ifdef HAVE_FUNLOCKFILE
- funlockfile (stderr);
-#endif
+ prologue (fp);
+
+ errno = err;
+ vfprintf (fp, fs, args);
+
+ fprintf (fp, "\n");
+ fclose (fp);
+
+ fputs (str, stderr);
errno = err;
}
@@ -86,25 +95,36 @@ nbdkit_vdebug (const char *fs, va_list args)
NBDKIT_DLL_PUBLIC void
nbdkit_debug (const char *fs, ...)
{
+ int err = errno;
va_list args;
- int err = errno;
+ CLEANUP_FREE char *str = NULL;
+ size_t len = 0;
+ FILE *fp;
if (!verbose)
return;
-#ifdef HAVE_FLOCKFILE
- flockfile (stderr);
-#endif
- prologue ();
+ fp = open_memstream (&str, &len);
+ if (fp == NULL) {
+ /* Try to emit what we can. */
+ va_start (args, fs);
+ errno = err;
+ vfprintf (stderr, fs, args);
+ va_end (args);
+ return;
+ }
+
+ prologue (fp);
va_start (args, fs);
- vfprintf (stderr, fs, args);
+ errno = err;
+ vfprintf (fp, fs, args);
va_end (args);
- fprintf (stderr, "\n");
-#ifdef HAVE_FUNLOCKFILE
- funlockfile (stderr);
-#endif
+ fprintf (fp, "\n");
+ fclose (fp);
+
+ fputs (str, stderr);
errno = err;
}
--
2.31.1