Created
July 10, 2023 16:52
-
-
Save zhuizhuhaomeng/2cbfde686725fd159985af5c045e48ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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