Skip to content

Instantly share code, notes, and snippets.

@zhuizhuhaomeng
Created July 10, 2023 16:52
Show Gist options
  • Save zhuizhuhaomeng/2cbfde686725fd159985af5c045e48ff to your computer and use it in GitHub Desktop.
Save zhuizhuhaomeng/2cbfde686725fd159985af5c045e48ff to your computer and use it in GitHub Desktop.
commit cf5b90dff53e0ebaba49073fe0c2d7e45f30cd52
Author: lijunlong <lijunlong@openresty.com>
Date: Mon Jul 10 13:17:46 2023 +0800
Bug: _stp_stack_user_sprint&_stp_stack_kernel_sprint flush the output buffer if the backtrace size greater than STP_BUFFER_SIZE.
diff --git a/runtime/linux/print.c b/runtime/linux/print.c
index db71871d2..98916d1ca 100644
--- a/runtime/linux/print.c
+++ b/runtime/linux/print.c
@@ -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);
}
diff --git a/runtime/print_flush.c b/runtime/print_flush.c
index 98963b3eb..35677b225 100644
--- a/runtime/print_flush.c
+++ b/runtime/print_flush.c
@@ -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);
diff --git a/runtime/stack.c b/runtime/stack.c
index cdcee4bdd..c5e975acd 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -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);
}
diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c
index 606f685e8..cdc929aa7 100644
--- a/runtime/vsprintf.c
+++ b/runtime/vsprintf.c
@@ -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;
diff --git a/testsuite/systemtap.base/ustack.exp b/testsuite/systemtap.base/ustack.exp
index 30671326a..9604d138f 100644
--- a/testsuite/systemtap.base/ustack.exp
+++ b/testsuite/systemtap.base/ustack.exp
@@ -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
index 000000000..d159562de
--- /dev/null
+++ b/testsuite/systemtap.base/ustack_3.c
@@ -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
index 000000000..01f462ab3
--- /dev/null
+++ b/testsuite/systemtap.base/ustack_3.stp
@@ -0,0 +1,5 @@
+probe process.function("mark") {
+ s = sprint_ubacktrace();
+ s = sprintf("bt: %s", s)
+ printf("%s", s);
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment