4 ms·
I concur with the author, it's an absolute mess. And I would love to see a single unified API for this. It's been a wish of mine for many years. Here are eve
by haberman 11y ago
I concur with the author, it's an absolute mess. And I would love to see a single unified API for this. It's been a wish of mine for many years.
Here are even more interfaces than the three the author listed (libunwind, __register_frame, GDB):
- oprofile has a JIT interface: http://oprofile.sourceforge.net/doc/devel/jit-interface.html http://oprofile.sourceforge.net/doc/devel/jit-interface.html
- perf has a JIT interface: https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt https://github.com/torvalds/linux/blob/master/tools/perf/Doc...
I wrote a blog article about the craziness around unwinding a few years back: http://blog.reverberate.org/2013/05/deep-wizardry-stack-unwinding.html http://blog.reverberate.org/2013/05/deep-wizardry-stack-unwi...
One of the questions I answer in my article which isn't addressed as much here is: why do we care about generating backtraces in the first place? It might seem obvious, but I identified four separate reasons which are all important: to support runtime exceptions (a la C++), to offer backtraces in debuggers, to sample the stack for profilers, and to print a backtrace from the program itself. So if you have a JIT and you don't offer proper backtraces, your users are going to be annoyed when they use any of these tools.
- pcwalton 11y agoYou probably knew this, but just to add in case others weren't aware: Those reasons are the reasons you want unwinding on Unix, but on Windows it's even more important. The Windows equivalent of Unix signals (very roughly speaking) is Structured Exception Handling (SEH), in which the kernel actually arranges for your stack to be unwound to deliver you signals such as segfaults [1]. So unless you maintain proper unwinding info, your app isn't in a position to receive any signals sent by the kernel (at least, the way you're intended to). [1]: http://www.nynaeve.net/?p=201 http://www.nynaeve.net/?p=201
- pjc50 11y agoThat blog looks very interesting, thanks. I found out the hard way that Microsoft has two sets of ARM compilers for WinCE7, and only one of them generates code that's compatible with the SEH unwinder. I don't think SEH actually calls destructors when unwinding C++, unlike C++ exceptions. This makes it leaky to use for anything other than fatal exceptions.
- wolfgke 11y ago> I don't think SEH actually calls destructors when unwinding C++, unlike C++ exceptions. This makes it leaky to use for anything other than fatal exceptions. How do you come to the conclusion that SEH is a leaky abstraction instead of the behavior of C++ destructors?
- jschwartzi 11y agoHe means it causes resource leaks in any classes that implement RAII.
- wolfgke 11y agoSEH was there before C++ was fully standardized (first standardized version was C++98). In this sense one can argue that the definition of RAII is leaky since it "forgot" that SEH was already there and not the other way round. A proper solution would have been that functions where RAII is used must not call functions that can throw an SEH exception.
- pjc50 11y agoAll kinds of functions can throw SEH exceptions, because they're machine check exceptions (divide by zero, reference invalid page/null pointer). I went and looked this up to refresh my memory: https://msdn.microsoft.com/en-us/library/swezty51.aspx https://msdn.microsoft.com/en-us/library/swezty51.aspx Microsoft recommend you don't mix the use of SEH exceptions with C++, or that you use the flag which turns SEH into C++ exceptions (and therefore calls destructors). In our case we didn't want to do that, because we're doing our own crash reporting and all we want is to log a backtrace while exiting the program, and do not want to call destructors which may themselves crash because the program is in an invalid state.
- wolfgke 11y agoTo me this all looks like stuff that is undefined behavior in C++, so a C++ program for which such a problem occurs is by definition invalid. In other words: You have a large problem in your code.
- evincarofautumn 11y agoWe mainly care about those reasons because many popular languages have exceptions and meaningful backtraces. If you remove exceptions, or add asynchronous/lazy/continuationful code, then the game becomes very different.