Preserve errno even if the function fails. We need to set errno = err again on every exit path out of the function.
Check if close_memstream failed and go to the error path if so. This is most important on Windows where close_memstream is what actually allocates the memory. But even on Unix, close_memstream (which is an alias for fclose) can return an error. Move the error-handling code to the end of the function. I added a comment above the 'fputs' explaining why exactly we're using memstream in the first place -- because it is more atomic than using multiple fprintf. See: https://listman.redhat.com/archives/libguestfs/2023-May/031456.html Thanks: Laszlo Ersek --- server/debug.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/server/debug.c b/server/debug.c index 8afa0ae8b..177d9d5da 100644 --- a/server/debug.c +++ b/server/debug.c @@ -81,14 +81,8 @@ debug_common (bool in_server, const char *fs, va_list args) FILE *fp; fp = open_memstream (&str, &len); - if (fp == NULL) { - fail: - /* Try to emit what we can. */ - errno = err; - vfprintf (stderr, fs, args); - fprintf (stderr, "\n"); - return; - } + if (fp == NULL) + goto fail; #ifndef WIN32 tty = isatty (fileno (stderr)); @@ -104,13 +98,23 @@ debug_common (bool in_server, const char *fs, va_list args) if (!in_server && tty) ansi_force_restore (fp); #endif fprintf (fp, "\n"); - close_memstream (fp); + if (close_memstream (fp) == -1) + goto fail; - if (str) - fputs (str, stderr); - else + if (!str) goto fail; + /* Send it to stderr as atomically as possible. */ + fputs (str, stderr); + + errno = err; + return; + + fail: + /* Try to emit what we can. */ + errno = err; + vfprintf (stderr, fs, args); + fprintf (stderr, "\n"); errno = err; } -- 2.39.2 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs