]> sourceware.org Git - systemtap.git/commitdiff
PR30634: stop flushing overlarge output to stapio for sprint* backtrace
authorlijunlong <lijunlong@openresty.com>
Thu, 13 Jul 2023 17:20:03 +0000 (13:20 -0400)
committerFrank Ch. Eigler <fche@redhat.com>
Thu, 13 Jul 2023 17:34:17 +0000 (13:34 -0400)
This could happen for example if MAXSTRINGLEN > STP_BUFFER_SIZE.

runtime/linux/print.c
runtime/print_flush.c
runtime/stack.c
runtime/vsprintf.c
testsuite/systemtap.base/ustack.exp
testsuite/systemtap.base/ustack_3.c [new file with mode: 0644]
testsuite/systemtap.base/ustack_3.stp [new file with mode: 0644]

index db71871d2ac9f684185228be136d8a7c36f666aa..98916d1ca42cb909e5982342182e7ba54504019b 100644 (file)
@@ -40,6 +40,8 @@ struct _stp_log {
        char *buf; /* NB we don't use arrays here to avoid allocating memory
                      on offline CPUs (but still possible ones) */
        atomic_t reentrancy_lock;
+       bool no_flush;
+       bool is_full;
 };
 #include "print_flush.c"
 
@@ -238,6 +240,9 @@ static void * _stp_reserve_bytes (int numbytes)
        if (unlikely(numbytes > (STP_BUFFER_SIZE - log->len)))
                __stp_print_flush(log);
 
+       if (log->is_full)
+               return NULL;
+
        ret = &log->buf[log->len];
        log->len += numbytes;
        return ret;
@@ -318,7 +323,7 @@ static void _stp_print (const char *str)
                return;
 
        log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
-       while (1) {
+       while (!log->is_full) {
                while (log->len < STP_BUFFER_SIZE && *str)
                        log->buf[log->len++] = *str++;
                if (likely(!*str))
@@ -339,7 +344,10 @@ static void _stp_print_char (const char c)
        log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
        if (unlikely(log->len == STP_BUFFER_SIZE))
                __stp_print_flush(log);
-       log->buf[log->len++] = c;
+
+       if (likely(!log->no_flush || !log->is_full))
+               log->buf[log->len++] = c;
+
        _stp_print_unlock_irqrestore(&flags);
 }
 
index 98963b3ebeeb7af776491dc8198714c903de07e2..35677b225c38dcee4e024ec75abee84b6ee1aaff 100644 (file)
@@ -27,6 +27,12 @@ static void __stp_print_flush(struct _stp_log *log)
        /* check to see if there is anything in the buffer */
        if (likely(len == 0))
                return;
+
+       if (unlikely(log->no_flush)) {
+               log->is_full = true;
+               return;
+       }
+
        log->len = 0; /* clear it for later reuse */
        dbug_trans(1, "len = %zu\n", len);
 
index cdcee4bddc5f64829054f4071b69844837007aeb..c5e975acd24cea8bf7f7d6d97242d2ffe36e739a 100644 (file)
@@ -685,6 +685,19 @@ static void _stp_stack_user_print(struct context *c, int sym_flags)
 #endif
 }
 
+static void __stp_sprint_begin(struct _stp_log *log)
+{
+       __stp_print_flush(log);
+       log->no_flush = true;
+}
+
+static void __stp_sprint_end(struct _stp_log *log)
+{
+       log->no_flush = false;
+       log->is_full = false;
+       log->len = 0;
+}
+
 /** Writes stack backtrace to a string
  *
  * @param str string
@@ -709,12 +722,12 @@ static void _stp_stack_kernel_sprint(char *str, int size, struct context* c,
        }
 
        log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
-       __stp_print_flush(log);
+       __stp_sprint_begin(log);
        _stp_stack_kernel_print(c, sym_flags);
        bytes = min_t(int, size - 1, log->len);
        memcpy(str, log->buf, bytes);
        str[bytes] = '\0';
-       log->len = 0;
+       __stp_sprint_end(log);
        _stp_print_unlock_irqrestore(&flags);
 }
 
@@ -736,12 +749,12 @@ static void _stp_stack_user_sprint(char *str, int size, struct context* c,
        }
 
        log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
-       __stp_print_flush(log);
+       __stp_sprint_begin(log);
        _stp_stack_user_print(c, sym_flags);
        bytes = min_t(int, size - 1, log->len);
        memcpy(str, log->buf, bytes);
        str[bytes] = '\0';
-       log->len = 0;
+       __stp_sprint_end(log);
        _stp_print_unlock_irqrestore(&flags);
 }
 
index 606f685e835ddfeb247e711a8dd894f1ad9af631..cdc929aa719e8bed9ee3e4f0414ddbe2aa8b7d7a 100644 (file)
@@ -730,7 +730,6 @@ _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
            return 0;
          str = (char*)_stp_reserve_bytes(num_bytes);
          if (str == NULL) {
-           _stp_error("Couldn't reserve any print buffer space\n");
            goto err_unlock;
          }
          got_print_lock = true;
index 30671326a975fe72b49e6df859240866717d164a..9604d138fea61782c4098827944047eb06b52e68 100644 (file)
@@ -47,3 +47,25 @@ if {$res ne ""} {
         send_log "stderr:\n$stderr"
     }
 }
+
+# --- TEST 3 ---
+
+set subtest3 "TEST 3: sprint_ubacktrace()"
+
+set res [target_compile ${testpath}/${test}_3.c ./a.out executable \
+    "additional_flags=-O additional_flags=-g additional_flags=-O0"]
+if {$res ne ""} {
+    verbose "target_compile failed: $res" 2
+    fail "$test: $subtest2: unable to compile ${test}_3.c"
+} else {
+    set test_name "$test: $subtest3"
+
+    set cmd "stap -DMAXBACKTRACE=256 --ldd -c ./a.out '$srcdir/$subdir/${test}_3.stp'"
+    set exit_code [run_cmd_2way $cmd out stderr]
+    set out_pat "bt: mark.*"
+    like "${test_name}: stdout" $out $out_pat ""
+    is "${test_name}: exit code" $exit_code 0
+    if {$stderr ne ""} {
+        send_log "stderr:\n$stderr"
+    }
+}
diff --git a/testsuite/systemtap.base/ustack_3.c b/testsuite/systemtap.base/ustack_3.c
new file mode 100644 (file)
index 0000000..d159562
--- /dev/null
@@ -0,0 +1,22 @@
+void mark()
+{
+}
+
+int my_func_name_is_very_longlonglonglonglonglonglonglonglonglonglong(int depth)
+{
+   int sum;
+
+   if (depth <= 0) {
+      mark();
+      return 0;
+   }
+
+   sum =  my_func_name_is_very_longlonglonglonglonglonglonglonglonglonglong(depth - 1);
+   sum += depth;
+   return sum;
+}
+
+int main(void) {
+    my_func_name_is_very_longlonglonglonglonglonglonglonglonglonglong(200);
+    return 0;
+}
diff --git a/testsuite/systemtap.base/ustack_3.stp b/testsuite/systemtap.base/ustack_3.stp
new file mode 100644 (file)
index 0000000..01f462a
--- /dev/null
@@ -0,0 +1,5 @@
+probe process.function("mark") {
+    s = sprint_ubacktrace();
+    s = sprintf("bt: %s", s)
+    printf("%s", s);
+}
This page took 0.03744 seconds and 5 git commands to generate.