authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-09 22:21:13-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-10 01:38:40-05:00
log3b3649b86f74d08013b669a6a4eac573f8d7fa23
tree751c3abd5d2f5be50b3305b6489ee36297b69db6
parent60b2031831320186f3920d63cfa35bda40930450

refactor stack trace code to remove global state


2 files changed, 22 insertions(+), 33 deletions(-)

std/debug/index.zig+20-28
......@@ -9,7 +9,6 @@ const macho = std.macho;
99const ArrayList = std.ArrayList;
1010const builtin = @import("builtin");
1111
12pub var stack_trace_start_address: ?usize = null;
1312pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
1413
1514/// Tries to write to stderr, unbuffered, and ignores any error returned.
......@@ -46,13 +45,13 @@ pub fn getSelfDebugInfo() !&ElfStackTrace {
4645}
4746
4847/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
49pub fn dumpCurrentStackTrace() void {
48pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
5049 const stderr = getStderrStream() catch return;
5150 const debug_info = getSelfDebugInfo() catch |err| {
5251 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;
5352 return;
5453 };
55 writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| {
54 writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty(), start_addr) catch |err| {
5655 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;
5756 return;
5857 };
......@@ -97,10 +96,18 @@ pub fn assertOrPanic(ok: bool) void {
9796 }
9897}
9998
100var panicking: u8 = 0; // TODO make this a bool
101/// This is the default panic implementation.
10299pub fn panic(comptime format: []const u8, args: ...) noreturn {
103100 @setCold(true);
101 const first_trace_addr = @ptrToInt(@returnAddress());
102 panicExtra(null, first_trace_addr, format, args);
103}
104
105var panicking: u8 = 0; // TODO make this a bool
106
107pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize,
108 comptime format: []const u8, args: ...) noreturn
109{
110 @setCold(true);
104111
105112 if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
106113 // Panicked during a panic.
......@@ -110,25 +117,12 @@ pub fn panic(comptime format: []const u8, args: ...) noreturn {
110117 // which first called panic can finish printing a stack trace.
111118 os.abort();
112119 }
113
114120 const stderr = getStderrStream() catch os.abort();
115121 stderr.print(format ++ "\n", args) catch os.abort();
116 dumpCurrentStackTrace();
117
118 os.abort();
119}
120
121pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) noreturn {
122 @setCold(true);
123
124 if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
125 // See TODO in above function
126 os.abort();
122 if (trace) |t| {
123 dumpStackTrace(t);
127124 }
128 const stderr = getStderrStream() catch os.abort();
129 stderr.print(format ++ "\n", args) catch os.abort();
130 dumpStackTrace(trace);
131 dumpCurrentStackTrace();
125 dumpCurrentStackTrace(first_trace_addr);
132126
133127 os.abort();
134128}
......@@ -161,18 +155,17 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var,
161155}
162156
163157pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
164 debug_info: &ElfStackTrace, tty_color: bool) !void
158 debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void
165159{
166160 const AddressState = union(enum) {
167161 NotLookingForStartAddress,
168162 LookingForStartAddress: usize,
169 FoundStartAddress,
170163 };
171164 // TODO: I want to express like this:
172 //var addr_state = if (stack_trace_start_address) |addr| AddressState { .LookingForStartAddress = addr }
165 //var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr }
173166 // else AddressState.NotLookingForStartAddress;
174167 var addr_state: AddressState = undefined;
175 if (stack_trace_start_address) |addr| {
168 if (start_addr) |addr| {
176169 addr_state = AddressState { .LookingForStartAddress = addr };
177170 } else {
178171 addr_state = AddressState.NotLookingForStartAddress;
......@@ -183,15 +176,14 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
183176 const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize));
184177
185178 switch (addr_state) {
186 AddressState.NotLookingForStartAddress => continue,
179 AddressState.NotLookingForStartAddress => {},
187180 AddressState.LookingForStartAddress => |addr| {
188181 if (return_address == addr) {
189 addr_state = AddressState.FoundStartAddress;
182 addr_state = AddressState.NotLookingForStartAddress;
190183 } else {
191184 continue;
192185 }
193186 },
194 AddressState.FoundStartAddress => {},
195187 }
196188 try printSourceAtAddress(debug_info, out_stream, return_address);
197189 }
std/special/panic.zig+2-5
......@@ -14,11 +14,8 @@ pub fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) noreturn
1414 while (true) {}
1515 },
1616 else => {
17 std.debug.stack_trace_start_address = @ptrToInt(@returnAddress());
18 if (error_return_trace) |trace| {
19 std.debug.panicWithTrace(trace, "{}", msg);
20 }
21 std.debug.panic("{}", msg);
17 const first_trace_addr = @ptrToInt(@returnAddress());
18 std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
2219 },
2320 }
2421}