]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pretty-print: introduce WITH_BUFFERED_STDERR macro to enable buffering 34205/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 31 Aug 2024 06:42:17 +0000 (15:42 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 3 Sep 2024 00:34:50 +0000 (09:34 +0900)
Then, the buffer will be flushed and buffering will be disabled on
exiting from the scope.

src/shared/pretty-print.c
src/shared/pretty-print.h
src/sysupdate/updatectl.c

index 9d3f6be1f4f3c776c7677a5e63e90d01dc42ede7..0360fa9d72a2db08284b2d2c1b9f26719ef08f43 100644 (file)
@@ -531,28 +531,14 @@ void clear_progress_bar_impl(const char *prefix) {
 }
 
 void draw_progress_bar(const char *prefix, double percentage) {
-
         /* We are going output a bunch of small strings that shall appear as a single line to STDERR which is
          * unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty
          * as a single buffer, to make things more efficient. */
-        char buffer[LONG_LINE_MAX];
-        setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
-
+        WITH_BUFFERED_STDERR;
         draw_progress_bar_impl(prefix, percentage);
-
-        fflush(stderr);
-
-        /* Disable buffering again */
-        setvbuf(stderr, NULL, _IONBF, 0);
 }
 
 void clear_progress_bar(const char *prefix) {
-        char buffer[LONG_LINE_MAX];
-        setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
-
+        WITH_BUFFERED_STDERR;
         clear_progress_bar_impl(prefix);
-
-        fflush(stderr);
-
-        setvbuf(stderr, NULL, _IONBF, 0);
 }
index 4efac1d7edcda9debaef86e7f4ebc7ec6406accb..446f305b733adbd4cf1f2a208ce0b826bf6ce655 100644 (file)
@@ -57,3 +57,32 @@ void draw_progress_bar(const char *prefix, double percentage);
 void clear_progress_bar(const char *prefix);
 void draw_progress_bar_impl(const char *prefix, double percentage);
 void clear_progress_bar_impl(const char *prefix);
+
+static inline FILE* enable_buffering(FILE *f, char *buffer, size_t size) {
+        assert(f);
+        assert(buffer);
+        assert(size > 0);
+
+        if (setvbuf(f, buffer, _IOFBF, size) != 0)
+                return NULL;
+
+        return f;
+}
+
+static inline void fflush_and_disable_bufferingp(FILE **p) {
+        assert(p);
+
+        if (*p) {
+                fflush(*p);
+                setvbuf(*p, NULL, _IONBF, 0); /* Disable buffering again. */
+        }
+}
+
+/* Even though the macro below is slightly generic, but it may not work most streams except for stderr,
+ * as stdout is buffered and fopen() enables buffering by default. */
+#define _WITH_BUFFERED_STREAM(f, size, p)                               \
+        _unused_ _cleanup_(fflush_and_disable_bufferingp) FILE *p =     \
+                enable_buffering(f, (char[size]) {}, size)
+
+#define WITH_BUFFERED_STDERR                                            \
+        _WITH_BUFFERED_STREAM(stderr, LONG_LINE_MAX, UNIQ_T(p, UNIQ))
index 87dd78b4c6dffb7ab253942f67116892570f1cb8..fad68ebd88191289664aab0bbd6fb49aa09c0fa2 100644 (file)
@@ -798,8 +798,7 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
 
         /* We're outputting lots of small strings to STDERR, which is unbuffered by default. So let's turn
          * on full buffering, so we pass this all to the TTY in one go, to make things more efficient */
-        char buffer[LONG_LINE_MAX];
-        setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
+        WITH_BUFFERED_STDERR;
 
         if (!terminal_is_dumb()) {
                 for (size_t i = 0; i <= n; i++)
@@ -855,8 +854,6 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
         } else if (!exiting)
                 fputs("------\n", stderr);
 
-        fflush(stderr);
-        setvbuf(stderr, NULL, _IONBF, 0); /* Disable buffering again */
         return 0;
 }