Hacker News new | ask | show | jobs
by elsamuko 1088 days ago
When I debug multithreaded programs, the stacktrace of a breakpoint usually ends somewhere in a worker thread. What I want is that the worker thread's stacktrace part is replaced by the one who put the work into it. Kinda like the program wasn't multithreaded at all.
3 comments

Ah. I guess you can capture the stack trace at task creation point, then stitch together a new stack trace by replacing the generic common prefix of your worker thread trace with the task creation one.

But you can't use the basic_stacktrace container itself as it is immutable and not constructibe from a range, so you have to roll your own. You should be able to use the stacktrace_entries though.

Most importantly, I expect that capturing a stacktrace is quite expensive, so you might not be able to do it at task creation time, and it is too late to do it later. Maybe you want this only in debug mode.

Note I haven't actually tried any if this, it is just guesswork.

Exactly this. I didn't try this, and I suppose that some low level pointer rewriting would be necessary to do this. I'm not sure if it's expensive though, maybe you can replace the pointers without resolving the stacktrace.
The problem is that to get the stacktrace of the task creation you have to traverse the stack at that point in time. You can't really do it later. And stack traversal using DWARF unwind info, for example, is neither cheap nor simple. You might have better luck if you compile with frame pointer though.
I think what you looking for is "task tracing" not really stack tracing. The relationship between the task (like where was a task added in the thread pool) are not reflected in the stacktrace the way you want them. To address those, you need to have special handshake between the debugger and your task api. You can also instrument the "add_task" function call to log every time a task is added to you queue and do some some offline stack stiching.
if you actually wanted to you could probably wrap thread to pass the stacktrace of the spawning thread into the worker thread whenever you spawn a thread and then output that upon a crash as well. the library seems pretty simple and flexible.