Skip to content

Instantly share code, notes, and snippets.

@zhuizhuhaomeng
Created June 28, 2023 08:16
Show Gist options
  • Save zhuizhuhaomeng/2a5c604eedb22b0cf07061aee0aadede to your computer and use it in GitHub Desktop.
Save zhuizhuhaomeng/2a5c604eedb22b0cf07061aee0aadede to your computer and use it in GitHub Desktop.
commit ffbb604ca72b709d8f77eebab7da97ec366c4f5b
Author: lijunlong <lijunlong@openresty.com>
Date: Wed Jun 28 16:10:40 2023 +0800
bugfix: _stp_stack_user_sprint flush the buffer to the terminal when the log->buf is full.
diff --git a/runtime/linux/print.c b/runtime/linux/print.c
index 594b155be..8dbb3a800 100644
--- a/runtime/linux/print.c
+++ b/runtime/linux/print.c
@@ -36,9 +36,13 @@
*/
struct _stp_log {
+ unsigned int dst_size;
+ unsigned int dst_len;
unsigned int len; /* Bytes used in the buffer */
char *buf; /* NB we don't use arrays here to avoid allocating memory
on offline CPUs (but still possible ones) */
+ char *dst; /* copy the buf into the dst when flushing buf for
+ _stp_snprintf */
atomic_t reentrancy_lock;
};
#include "print_flush.c"
diff --git a/runtime/print_flush.c b/runtime/print_flush.c
index 98963b3eb..f12431e0a 100644
--- a/runtime/print_flush.c
+++ b/runtime/print_flush.c
@@ -30,6 +30,17 @@ static void __stp_print_flush(struct _stp_log *log)
log->len = 0; /* clear it for later reuse */
dbug_trans(1, "len = %zu\n", len);
+ if (log->dst != NULL) {
+ if (log->dst_len < log->dst_size) {
+ size_t bytes;
+
+ bytes = min_t(int, log->dst_size - log->dst_len, len);
+ memcpy(log->dst + log->dst_len, bufp, bytes);
+ log->dst_len += bytes;
+ }
+ return;
+ }
+
/* try to reserve header + len */
bytes_reserved = _stp_data_write_reserve(hlen+len,
&entry);
diff --git a/runtime/stack.c b/runtime/stack.c
index cdcee4bdd..011ec536d 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -709,12 +709,25 @@ static void _stp_stack_kernel_sprint(char *str, int size, struct context* c,
}
log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
+ log->dst = str;
+ log->dst_size = size - 1;
+ log->dst_len = 0;
+
__stp_print_flush(log);
_stp_stack_kernel_print(c, sym_flags);
- bytes = min_t(int, size - 1, log->len);
- memcpy(str, log->buf, bytes);
+
+ bytes = min_t(int, size - 1 - log->dst_len, log->len);
+ if (bytes > 0)
+ memcpy(str + log->dst_len, log->buf, bytes);
+ bytes += log->dst_len;
+ if ((sym_flags & _STP_SYM_POST_SPACE) && bytes > 0 && str[bytes] == ' ')
+ bytes--;
str[bytes] = '\0';
log->len = 0;
+ log->dst = NULL;
+ log->dst_size = 0;
+ log->dst_len = 0;
+
_stp_print_unlock_irqrestore(&flags);
}
@@ -737,11 +750,23 @@ 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);
+ log->dst = str;
+ log->dst_size = size - 1;
+ log->dst_len = 0;
+
_stp_stack_user_print(c, sym_flags);
- bytes = min_t(int, size - 1, log->len);
- memcpy(str, log->buf, bytes);
+ bytes = min_t(int, size - 1 - log->dst_len, log->len);
+ if (bytes > 0)
+ memcpy(str + log->dst_len, log->buf, bytes);
+ bytes += log->dst_len;
+ if ((sym_flags & _STP_SYM_POST_SPACE) && bytes > 0 && str[bytes] == ' ')
+ bytes--;
str[bytes] = '\0';
log->len = 0;
+ log->dst = NULL;
+ log->dst_size = 0;
+ log->dst_len = 0;
+
_stp_print_unlock_irqrestore(&flags);
}
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