1

When I run my executable outside of the debugger I get this assertion which triggers a trap:

Apr 29 08:25:21  ./xmlpgtest_doccopy[39308] <Error>: <Error>: Assert:[/Users/davidbien/dv/xmlp/xmlpinc/xml_tag.h:49],void ns_xmlp::xml_tag<ns_xmlp::xml_traits<ns_lxo::_l_transport_file<char8_t>, false, false>>::AssertValid(const ns_xmlp::xml_tag::_TyThis *) const [t_TyXmlTraits = ns_xmlp::xml_traits<ns_lxo::_l_transport_file<char8_t>, false, false>](): _ptagParent == m_ptagParent.
[1]    39308 trace trap  ./xmlpgtest_doccopy ~/dv/xmlp/unittests/unittest1.xml

However when I run inside of LLDB inside of Visual Studio Code the debugger just hangs and doesn't catch the TRAP signal. If I press the "PAUSE" button it just stops debugging with the message:

The program '/Users/davidbien/dv/xmlp/build/xmlpgtest_doccopy' has exited with code 0 (0x00000000).

So I am having quite a hard time debugging this. This doesn't happen (for instance) when debugging under Visual Studio Code with GDB under Linux and of course I can debug under MSVC in Windows.

Any help would be appreciated. Please no ridicule, I am a C++ developer for the last 28 years, I know what I am doing.

I looked at various potential solutions on here, including one where someone suggests to send a TRAP signal from a command window to the inferior LLDB process (the one being debugged) and that doesn't have any effect whatsoever.

Here is how I am breaking into the debugger in various OS/compiler combinations:

#ifdef _MSC_VER
#define DEBUG_BREAK __debugbreak()
#elif defined( __clang__ )
#if __has_builtin(__builtin_debugtrap)
#define DEBUG_BREAK __builtin_debugtrap()
#else
#define DEBUG_BREAK __builtin_trap()
#endif
#elif defined( __GNUC__ )
#define DEBUG_BREAK __builtin_trap()
#else
#error Need to know the OS/compiler for breaking into the debugger.
#endif

I am compiling using clang12 from the latest Xcode release and the latest lldb from the same release.

EDIT: I do break on an AV (access violation) so perhaps I should just AV instead of raising a TRAP signal?

EDIT: I did as Ben suggested below (thanks Ben) and the result is no change in behavior.

-exec process handle -p TRUE -s TRUE SIGTRAP
NAME         PASS   STOP   NOTIFY
===========  =====  =====  ======
SIGTRAP      true   true   true 

It still hangs when the SIGTRAP is sent.

EDIT: I inserted:

*((volatile char*)0) = 0xba;
DEBUG_BREAK;

in the hopes that I could just have an AV break into the debugger. The debugger still hangs.

EDIT: The VisualStudioCode extension CodeLLDB works and gets to my assertion and has some other really awesome things - like tells you the active type of a variant. The bug is apparently in lldb-mi which is released by Microsoft. I may give them a bug.

SUMMARY: This is due to a bug in lldb-mi.

David Bien
  • 622
  • 5
  • 10
  • You'd probably get the same behavior from gdb after running `handle SIGTRAP noprint nostop`. Signal handling in debuggers is configurable... – Ben Voigt Apr 29 '21 at 15:52
  • @BenVoigt Is that an actionable comment? – David Bien Apr 29 '21 at 15:53
  • Probably helpful (it discusses configuring lldb signal handling in context of a different signal, you should be able to adapt it to SIGTRAP): https://stackoverflow.com/a/12649223/103167 – Ben Voigt Apr 29 '21 at 15:54
  • @BenVoigt Thanks - that's a good rabbit hole to go down at least. – David Bien Apr 29 '21 at 15:55
  • Sure it is actionable, you could run that command in gdb and learn "hey lldb is behaving exactly the same as gdb in nostop configuration" or "actually it still behaves differently, so it isn't likely to be the debugger signal configuration". Also, knowing the gdb command gives keywords to use when searching for the lldb command. – Ben Voigt Apr 29 '21 at 15:55
  • @BenVoigt I'm on vacation and I brought my MacBook and that's why I am using lldb. gdb doesn't seem to exist on this machine. – David Bien Apr 29 '21 at 15:56
  • @BenVoigt any other ideas? As I indicated in my edit above: No change in behavior when I tell lldb to stop on a SIGTRAP. – David Bien Apr 29 '21 at 16:26
  • How does that table compare to how your other signals are configured, such as the AV that stops correctly in the debugger? `-p TRUE` strikes me as suspicious, you want that signal processed by the debugger not the inferior. – Ben Voigt Apr 29 '21 at 17:16
  • apparently i lack a brain? what about putting a breakpoint where i call DEBUG_BREAK? lol. I’ll also try what you suggest and let you know for completeness. – David Bien Apr 29 '21 at 17:51
  • Well conveniently LLDB can't map the source to the binary for the breakpoint inside of the "assertion failed" code in an INL header file... that's the most annoying thing about GDB and LLDB: they have a hard time finding inlines and template methods. My library is header only so this is particularly frustrating to me. – David Bien Apr 29 '21 at 18:01
  • That also may be why LLDB is hanging - I mean it should break in disassembly like MSVC would but perhaps it doesn't do that... not very familiar with LLDB. – David Bien Apr 29 '21 at 18:03
  • @BenVoigt Lol. Actually I must've thought the same thing because cycling back through my LLDB commands I found "-exec process handle -p FALSE -s TRUE SIGTRAP" and nada... hmmm. Gonna have to try this with a really small application - my application is huge and the debug info is even huger because this is my unittest and I am instantiating all potential template types for completeness. It didn't blow out GDB or MSVC but perhaps it is blowing out LLDB/VisualStudioCode? Hard to say. I can also just run LLDB command line but that is annoying as heck. – David Bien Apr 29 '21 at 18:21
  • The trap you insert with builtin_debug_trap is the same trap as lldb inserts to implement a breakpoint. The only difference in the handling is that lldb checks to see if IT was the one that inserted the trap. If yes, breakpoint, if no, you see the trap as an EXC_BREAKPOINT. If you app is stalling when it stops at your trap, it is much more likely that something else is causing that. When it stops, the IDE is probably asking for the list of threads, and frames, and the local variables and etc... Any of those could be stalling. – Jim Ingham Apr 29 '21 at 18:35
  • IIRC, VSCode on the Mac uses lldb-vscode as its lldb agent. You could try sampling that when you are stalling. You might be able to tell from that sample what work is causing the stall. – Jim Ingham Apr 29 '21 at 18:39
  • @JimIngham Thanks Jim. At this point - especially after inserting an AV and that not working either - I am thinking it is indeed something else. I had an AV very early in program execution (that I fixed) and that showed in the debugger. There is only one thread. I am thinking maybe try the command line version. Also thinking about trying to run in Xcode directly but I haven't ever used Xcode before. I was debugging on my iMac a year ago or so before porting to Window and I am also wondering is this might be due to Xcode/BigSur upgrade, etc. – David Bien Apr 29 '21 at 18:40
  • @JimIngham Wrt your idea re: lldb-vscode: What do you mean sampling, etc? Thanks. – David Bien Apr 29 '21 at 18:43
  • @JimIngham When I try anything while the debugger is hung I get "Unable to perform this action because the process is running." – David Bien Apr 29 '21 at 18:50
  • In MSVC I can force a break into the debugger at any time the binary is running. Is there a command line version of this for LLDB: something like "break now"? – David Bien Apr 29 '21 at 18:51
  • Sorry, I wasn't clear. By "sample" I mean run the "sample" command-line tool either on the process by name or on the pid. That will produce a time-based profile of what lldb-vscode is doing. That might tell you why this is stalling. – Jim Ingham Apr 30 '21 at 17:00
  • In command line lldb, ^C will interrupt the process if it is running. However, if the stop is stalling because of work that the debugger is doing after the stop, ^C won't necessarily interrupt that. Not sure how you interrupt in vscode. – Jim Ingham Apr 30 '21 at 17:01
  • I noticed the fan on my MacBook was just running all the time. There were three lldb-mi (which VisualStudioCode runs apparently) instances running at 100% CPU in the background. This is a bug in the debugger - or VisualStudioCode I think, which really sucks. I found the spot where it hangs: I put a break point on one method, I step into the next, and hang. No more responding after that. I don't have any visibility into why it might be hanging. Multiple template instances with different types mucking with the compiler? Unknown. I'll try stuff but I am thinking: Xcode - gotta convert the project – David Bien Apr 30 '21 at 17:57
  • As soon as I step into the "hanging method" lldb-mi runs at 100% CPU. Which is probably an endless loop of some sort. My code is running perfectly with no leaks, etc. on Windows and Linux so I highly doubt it is my code and indeed I am in a method that does very little - except hang the debugger. – David Bien Apr 30 '21 at 17:59
  • Apparently there are multiple instances of lldb-mi and also I may be able to download a previous version and use that if I change where VisualStudioCode points to a given LLDB.framework. This is where things get hairy - and the Mac is the most opaque of OSes - at least perhaps due to the fact that I have never professionally developed on it - but it is so close to Linux that the code difference are miniscule - just a few #ifdef's difference between Mac and Linux. – David Bien Apr 30 '21 at 18:27
  • The extension CodeLLDB works and gets to my assertion and has some other really awesome things - like tells you the active type of a variant. The bug is apparently in lldb-mi which is released by Microsoft. I may give them a bug. – David Bien May 02 '21 at 06:16
  • In case this background helps: The MI (Machine Interface) is an older interface invented to provide a structured way to drive gdb. Eclipse uses it, so an lldb adaptor was made: lldb-mi. But the maintainers lost interest and nobody else stepped up, so it hasn't seen a lot of attention recently. Another group made a different adaptor (lldb-vscode) which uses the MS debugging protocol instead of the MI. That is what CodeLLDB uses. lldb-vscode is in active development, so it's not surprising that you are having more success with a debugger that uses the lldb-vscode adaptor. – Jim Ingham May 05 '21 at 02:02
  • Thanks @JimIngham. And I found my assertion issue and now I'll probably only develop on the Mac or Linux when I need to. I have admit that I am more impressed with CodeLLDB than I was expecting to be. I've debugged under MSVC (professionally and otherwise) since 1995 or so and it works really well - with hardware breakpoints and non-hardware conditional breakpoints etc. I was been impressed that I was actually able to set a conditional breakpoint in WSL2 running Ubuntu and it worked - I hadn't expected it to. The days of printf debugging might finally be over - lol. – David Bien May 05 '21 at 02:39
  • Also MSVC is now allowing you to access typedefs and use them in inspection statements in the debugger - which is crazy awesome. And allows you to call inline methods of course - it's done that for quite a while. Oh - the other thing I was happily surprised to see was that I was able to reset the execution point on WSL2 running Ubuntu and debugging from MSVC IDE - this is so key sometimes. – David Bien May 05 '21 at 02:43

0 Answers0