Commit a4523a2d4a

Cody Tapscott <topolarity@tapscott.me>
2022-09-26 05:18:15
builtin.zig: Do not overwrite error frames when trace full
Previously, we'd overwrite the errors in a circular buffer. Now that error return traces are intended to follow a stack discipline, we no longer have to support the index rolling over. By treating the trace like a saturating stack, any pop/restore code still behaves correctly past-the-end of the trace. As a bonus, this adds a small blurb to let the user know when the trace saturated and x number of frames were dropped.
1 parent d060cbb
Changed files (2)
lib/std/builtin.zig
@@ -869,8 +869,10 @@ pub noinline fn returnError(st: *StackTrace) void {
 }
 
 pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {
-    st.instruction_addresses[st.index & (st.instruction_addresses.len - 1)] = addr;
-    st.index +%= 1;
+    if (st.index < st.instruction_addresses.len)
+        st.instruction_addresses[st.index] = addr;
+
+    st.index += 1;
 }
 
 const std = @import("std.zig");
lib/std/debug.zig
@@ -411,6 +411,14 @@ pub fn writeStackTrace(
         const return_address = stack_trace.instruction_addresses[frame_index];
         try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
     }
+
+    if (stack_trace.index > stack_trace.instruction_addresses.len) {
+        const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
+
+        tty_config.setColor(out_stream, .Bold);
+        try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
+        tty_config.setColor(out_stream, .Reset);
+    }
 }
 
 pub const StackIterator = struct {