digitalmars.D.learn - Print only part of a stack trace
- Dennis (9/9) Jul 01 2020 On assertion failure, the default error handler prints a stack
- Jacob Carlborg (5/16) Jul 01 2020 Could `Runtime.traceHandler` [1] be that you're looking for?
- Dennis (25/27) Jul 01 2020 Thanks, but I don't want to re-implement the default trace
- Stanislav Blinov (10/29) Jul 01 2020 void assertNoOpenGLErrors(string file = __FILE__, int line =
- Dennis (20/29) Jul 01 2020 I love __FILE__ and __LINE__, but in this case they won't cut it.
- Dennis (7/11) Jul 01 2020 So dmd skips the first 5 stack frames to account for
- JN (7/16) Jul 01 2020 Bit off-topic, but if you can use them, debug contexts offer much
- Dennis (12/18) Jul 01 2020 I use those as well, to get a more detailed message about the
- Adam D. Ruppe (34/36) Jul 01 2020 My cgi.d does something just like that. It just does
On assertion failure, the default error handler prints a stack trace that looks like this [library functions] [application functions] [druntime start-up functions] I'm only interested in application functions, the rest is noise. I could easily filter unwanted lines out if I had the stack trace in string form, but I don't know how to obtain that. Is there a simple way to do this, or should I delve into Druntime internals?
Jul 01 2020
On 2020-07-01 19:44, Dennis wrote:On assertion failure, the default error handler prints a stack trace that looks like this [library functions] [application functions] [druntime start-up functions] I'm only interested in application functions, the rest is noise. I could easily filter unwanted lines out if I had the stack trace in string form, but I don't know how to obtain that. Is there a simple way to do this, or should I delve into Druntime internals?Could `Runtime.traceHandler` [1] be that you're looking for? [1] https://dlang.org/phobos/core_runtime.html#.Runtime.traceHandler -- /Jacob Carlborg
Jul 01 2020
On Wednesday, 1 July 2020 at 18:05:09 UTC, Jacob Carlborg wrote:[1] https://dlang.org/phobos/core_runtime.html#.Runtime.traceHandlerThanks, but I don't want to re-implement the default trace handler, I want to use it on a specific location and capture its output. I'll be more specific in what I want to achieve. I have a function that checks a global error constant of a C library (OpenGL) like this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { assert(0); // stack trace points to here instead of caller } } ``` And I would like to rewrite it to this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { print(getStackTrace().filterTrace()); exit(); } } ``` So that the stack trace immediately points to the function that raised the OpenGL error, instead of it being buried in a large trace.
Jul 01 2020
On Wednesday, 1 July 2020 at 18:30:15 UTC, Dennis wrote:I have a function that checks a global error constant of a C library (OpenGL) like this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { assert(0); // stack trace points to here instead of caller } } ``` And I would like to rewrite it to this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { print(getStackTrace().filterTrace()); exit(); } } ```void assertNoOpenGLErrors(string file = __FILE__, int line = __LINE__, string func = __PRETTY_FUNCTION__) { if (glGetError() != GL_NO_ERROR) { print(file, ":", line, ":", func, ": blah"); exit(); } } :)
Jul 01 2020
On Wednesday, 1 July 2020 at 18:44:10 UTC, Stanislav Blinov wrote:void assertNoOpenGLErrors(string file = __FILE__, int line = __LINE__, string func = __PRETTY_FUNCTION__) { if (glGetError() != GL_NO_ERROR) { print(file, ":", line, ":", func, ": blah"); exit(); } } :)I love __FILE__ and __LINE__, but in this case they won't cut it. In my actual code there's usually one or two more functions inbetween, and amending hundreds of signatures with __FILE__ and __LINE__ for a little debugging convenience is not worth it. I'm now trying to call the defaultTraceHandler manually like this: ``` void bar() { import std.stdio; import core.runtime: defaultTraceHandler; auto res = defaultTraceHandler(null); writeln(res); } void foo() {bar();} void main() {foo();} ``` It sort of works, but it seems it does not start at the right stack frame, the top item is this: ??:? void rt.dmain2._d_run_main2(char[][], ulong, extern (C) int function(char[][])*).runAll().__lambda1() [0x55c19a09c1fa]
Jul 01 2020
On Wednesday, 1 July 2020 at 18:54:55 UTC, Dennis wrote:It sort of works, but it seems it does not start at the right stack frame, the top item is this: ??:? void rt.dmain2._d_run_main2(char[][], ulong, extern (C) int function(char[][])*).runAll().__lambda1() [0x55c19a09c1fa]So dmd skips the first 5 stack frames to account for _d_traceContext, _d_createTrace etc, while ldc filters out by filename. https://github.com/ldc-developers/druntime/blob/cc97ccd00d4082221eee1d5afdbd775201d75877/src/core/runtime.d#L855 I can easily work around this, though it's unfortunate that the public API of DefaultTraceInfo has this limitation.
Jul 01 2020
On Wednesday, 1 July 2020 at 18:30:15 UTC, Dennis wrote:I have a function that checks a global error constant of a C library (OpenGL) like this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { assert(0); // stack trace points to here instead of caller } }Bit off-topic, but if you can use them, debug contexts offer much better OpenGL error-checking experience. https://www.khronos.org/opengl/wiki/Debug_Output . Instead of checking glGetError() after each call, you can setup a C callback that will trigger whenever an error occurs. It also offers some vendor-specific performance warnings.
Jul 01 2020
On Wednesday, 1 July 2020 at 19:33:08 UTC, JN wrote:Bit off-topic, but if you can use them, debug contexts offer much better OpenGL error-checking experience. https://www.khronos.org/opengl/wiki/Debug_Output . Instead of checking glGetError() after each call, you can setup a C callback that will trigger whenever an error occurs. It also offers some vendor-specific performance warnings.I use those as well, to get a more detailed message about the error than the error code alone. While it helps describing _what_ went wrong, it doesn't tell me _where_ it went wrong. I tried doing assert(0) in the callback, but even with glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS), the stack trace looks something like this: app.d: debugCallback [0x559eda75c7e8] ??:? [0x7f4a0bffa7d7] And then it ends. It seems like it goes up into the OpenGL dll and then gets stuck, it does not trace back to the call site of the glFunction that failed.
Jul 01 2020
On Wednesday, 1 July 2020 at 17:44:45 UTC, Dennis wrote:On assertion failure, the default error handler prints a stack trace that looks like thisMy cgi.d does something just like that. It just does `exception.toString()` then `splitLines` on that string. Element exceptionToElement(Throwable t) { auto div = Element.make("div"); div.addClass("exception-display"); div.addChild("p", t.msg); div.addChild("p", "Inner code origin: " ~ typeid(t).name ~ " " ~ t.file ~ ":" ~ to!string(t.line)); auto pre = div.addChild("pre"); string s; s = t.toString(); Element currentBox; bool on = false; foreach(line; s.splitLines) { if(!on && line.startsWith("-----")) on = true; if(!on) continue; if(line.indexOf("arsd/") != -1) { if(currentBox is null) { currentBox = pre.addChild("details"); currentBox.addChild("summary", "Framework code"); } currentBox.addChild("span", line ~ "\n"); } else { pre.addChild("span", line ~ "\n"); currentBox = null; } } return div; }
Jul 01 2020