This could happen for example if MAXSTRINGLEN > STP_BUFFER_SIZE.
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"
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;
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))
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);
}
/* 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);
#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
}
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);
}
}
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);
}
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;
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"
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+probe process.function("mark") {
+ s = sprint_ubacktrace();
+ s = sprintf("bt: %s", s)
+ printf("%s", s);
+}