diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -1320,6 +1320,53 @@ } }; +class CommandObjectThreadSiginfo : public CommandObjectIterateOverThreads { +public: + CommandObjectThreadSiginfo(CommandInterpreter &interpreter) + : CommandObjectIterateOverThreads( + interpreter, "thread siginfo", + "Display the current siginfo object for a thread. Defaults to " + "the current thread.", + "thread siginfo", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} + + ~CommandObjectThreadSiginfo() override = default; + + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, + request, nullptr); + } + + bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { + ThreadSP thread_sp = + m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); + if (!thread_sp) { + result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", + tid); + return false; + } + + Stream &strm = result.GetOutputStream(); + if (!thread_sp->GetDescription(strm, eDescriptionLevelFull, false, false)) { + result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", + thread_sp->GetIndexID()); + return false; + } + ValueObjectSP exception_object_sp = thread_sp->GetSiginfoValue(); + if (exception_object_sp) + exception_object_sp->Dump(strm); + else + strm.Printf("(no siginfo)\n"); + strm.PutChar('\n'); + + return true; + } +}; + // CommandObjectThreadReturn #define LLDB_OPTIONS_thread_return #include "CommandOptions.inc" @@ -2293,6 +2340,8 @@ CommandObjectSP(new CommandObjectThreadInfo(interpreter))); LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException( interpreter))); + LoadSubCommand("siginfo", + CommandObjectSP(new CommandObjectThreadSiginfo(interpreter))); LoadSubCommand("step-in", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-in", diff --git a/lldb/test/Shell/Commands/Inputs/sigchld.c b/lldb/test/Shell/Commands/Inputs/sigchld.c new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Commands/Inputs/sigchld.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +void handler(int signo) { + printf("SIGCHLD\n"); +} + +int main() { + void *ret = signal(SIGINT, handler); + assert (ret != SIG_ERR); + + pid_t child_pid = fork(); + assert (child_pid != -1); + + if (child_pid == 0) { + sleep(1); + _exit(14); + } + + printf("signo = %d\n", SIGCHLD); + printf("code = %d\n", CLD_EXITED); + printf("child_pid = %d\n", child_pid); + printf("uid = %d\n", getuid()); + pid_t waited = wait(NULL); + assert(waited == child_pid); + + return 0; +} diff --git a/lldb/test/Shell/Commands/command-thread-siginfo.test b/lldb/test/Shell/Commands/command-thread-siginfo.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Commands/command-thread-siginfo.test @@ -0,0 +1,19 @@ +# REQUIRES: system-linux +# RUN: %clang_host -g %S/Inputs/sigchld.c -o %t +# RUN: %lldb %t -b -s %s | FileCheck %s + +process launch -s +process handle SIGCHLD -s true +process continue +# CHECK: signo = [[SIGNO:[0-9]+]] +# CHECK: code = [[CODE:[0-9]+]] +# CHECK: child_pid = [[PID:[0-9]+]] +# CHECK: uid = [[UID:[0-9]+]] +# CHECK: stop reason = signal SIGCHLD +thread siginfo +# CHECK-DAG: si_signo = [[SIGNO]] +# CHECK-DAG: si_errno = 0 +# CHECK-DAG: si_code = [[CODE]] +# CHECK-DAG: si_pid = [[PID]] +# CHECK-DAG: si_uid = [[UID]] +# CHECK-DAG: si_status = 14