Skip to content

[LLDB] options --source-on-crash and --one-line-on-crash are ignored if crash happens in a non-main thread #58525

@DoDoENT

Description

@DoDoENT

Consider this program:

#include <cstdio>
#include <thread>

int main()
{
    auto crasher
    {
        []()
        {
            int * p = reinterpret_cast< int * >( 42 );
            std::printf( "Evil number: %d\n", *p );
        }
    };

    std::thread cthread{ crasher };

    cthread.join();
    return 0;
}

Compile it with clang++ crash.cpp -std=c++20 -o crash and then run under LLDB with following command:

lldb --batch --one-line 'run' --one-line-on-crash 'thread backtrace all'  --one-line-on-crash 'quit 1' -- ./crash

The output on my M1 MacPro is

(lldb) run
Process 41725 stopped
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x2a)
    frame #0: 0x00000001000039e8 crash`main::$_0::operator()() const + 28
crash`main::$_0::operator()() const:
->  0x1000039e8 <+28>: ldr    w9, [x8]
    0x1000039ec <+32>: mov    x8, x9
    0x1000039f0 <+36>: mov    x9, sp
    0x1000039f4 <+40>: str    x8, [x9]
Target 0: (crash) stopped.
Process 41725 launched: '/Users/dodo/builds/core-neural-network/clang/release/crash' (arm64)

As you can see, thread backtrace all wasn't executed. You can easily verify that by comparing the output when running LLDB in an interactive mode:

[dodo@nm-nmiksa: release]$ lldb -- ./crash
(lldb) target create "./crash"
Current executable set to '/Users/dodo/builds/core-neural-network/clang/release/crash' (arm64).
(lldb) run
Process 51423 launched: '/Users/dodo/builds/core-neural-network/clang/release/crash' (arm64)
Process 51423 stopped
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x2a)
    frame #0: 0x00000001000039e8 crash`main::$_0::operator()() const + 28
crash`main::$_0::operator()() const:
->  0x1000039e8 <+28>: ldr    w9, [x8]
    0x1000039ec <+32>: mov    x8, x9
    0x1000039f0 <+36>: mov    x9, sp
    0x1000039f4 <+40>: str    x8, [x9]
Target 0: (crash) stopped.
(lldb) thread backtrace all
  thread #1, queue = 'com.apple.main-thread'
    frame #0: 0x000000019f418834 libsystem_kernel.dylib`__ulock_wait + 8
    frame #1: 0x000000019f4565a0 libsystem_pthread.dylib`_pthread_join + 444
    frame #2: 0x000000019f3afa14 libc++.1.dylib`std::__1::thread::join() + 36
    frame #3: 0x0000000100002dac crash`main + 52
    frame #4: 0x000000010001108c dyld`start + 520
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x2a)
  * frame #0: 0x00000001000039e8 crash`main::$_0::operator()() const + 28
    frame #1: 0x0000000100003988 crash`decltype(static_cast<main::$_0>(fp)()) std::__1::__invoke<main::$_0>(main::$_0&&) + 24
    frame #2: 0x0000000100003924 crash`void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, main::$_0>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, main::$_0>&, std::__1::__tuple_indices<>) + 32
    frame #3: 0x00000001000030f4 crash`void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, main::$_0> >(void*) + 84
    frame #4: 0x000000019f45426c libsystem_pthread.dylib`_pthread_start + 148
(lldb) quit
Quitting LLDB will kill one or more processes. Do you really want to proceed: [Y/n] y

However, if I cause a crash on the main thread (in function main), like this:

#include <cstdio>
#include <thread>

int main()
{
    auto crasher
    {
        []()
        {
            int * p = reinterpret_cast< int * >( 42 );
            std::printf( "Evil number: %d\n", *p );
        }
    };

    // std::thread cthread{ crasher };

    // cthread.join();
    crasher();
    return 0;
}

then LLDB works as expected:

[dodo@nm-nmiksa: release]$ lldb --batch --one-line 'run' --one-line-on-crash 'thread backtrace all' --one-line-on-crash 'quit 1'  -- ./crash
(lldb) target create "./crash"
Current executable set to '/Users/dodo/builds/core-neural-network/clang/release/crash' (arm64).
(lldb) run
Process 59018 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2a)
    frame #0: 0x0000000100003f70 crash`main::$_0::operator()() const + 28
crash`main::$_0::operator()() const:
->  0x100003f70 <+28>: ldr    w9, [x8]
    0x100003f74 <+32>: mov    x8, x9
    0x100003f78 <+36>: mov    x9, sp
    0x100003f7c <+40>: str    x8, [x9]
Target 0: (crash) stopped.
Process 59018 launched: '/Users/dodo/builds/core-neural-network/clang/release/crash' (arm64)
(lldb) thread backtrace all
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2a)
  * frame #0: 0x0000000100003f70 crash`main::$_0::operator()() const + 28
    frame #1: 0x0000000100003f44 crash`main + 44
    frame #2: 0x000000010001108c dyld`start + 520
(lldb) quit 1

I can reproduce that with 1400.0.30.3, shipped with Xcode 14.0.1 and also with LLDB v15.0.3 compiled from LLVM source 15.0.3 on Linux.

Also, if I put the commands into a file and use --source-on-crash instead of --one-line-on-crash I get the same behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions