forking lldb to get a complete backtrace

I'm trying to use a technique we use on Linux to get a stack trace of a process that gets in trouble. We fork a debugger in batch mode in a child process to get the back trace of the parent. When I run this, lldb hangs in the attach to the parent process. And since lldb cannot attach to lldb, there's no way for me to see what's blocking lldb in the attach to the parent. Attached is a simple program that demonstrates the problem. Manually running lldb from a shell with the same arguments gets the stack trace. Is there some way around this hang?
Code Block language C++
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <errno.h>
#include <poll.h>
static void runChild(pid_t parent) {
const char *lldb = "/usr/bin/lldb";
const char * args[8];
char pidstr[16];
snprintf(pidstr, sizeof(pidstr), "%d", (int) parent);
args[0] = lldb;
args[1] = "--no-lldbinit";
args[2] = "--batch";
args[3] = "-p";
args[4] = pidstr;
args[5] = "--one-line";
args[6] = "thread backtrace all";
args[7] = NULL;
errno = 0;
char * const * _args = (char * const *) args;
int rc = execv(lldb, _args);
int saveErrno = errno;
if (rc) {
printf("execv failure, errno = %d\n", saveErrno);
}
_exit(1);
}
int main(int argc, const char *argv[]) {
pid_t parent= getpid();
pid_t child = fork();
if (child == -1) {
printf("fork() failure\n");
exit(1);
}
if (child == 0) {
// we are the child process
runChild(parent);
}
// so we are the parent
printf("Waiting for child %d to exit\n", (int) child);
fflush(stdout);
for (;;) {
errno = 0;
int status = 0;
pid_t result = waitpid(child, &status, WNOHANG | WUNTRACED);
int saveErrno = errno;
printf("waitpid: rc=%d, exited %d, signaled %d, stopped %d\n",
(int) result, WIFEXITED(status), WIFSIGNALED(status), WIFSIGNALED(status));
if (result == -1)
break;
poll(NULL, 0, 1000); // sleep for 1 s and retry
}
exit(0);
return 0;
}



Works for me ¯\_(ツ)_/¯. LLDB should be able to attach to LLDB, what error are you getting?
Have you considered using sample(1) or spindump(8)? macOS comes with tools to generate backtraces externally without jumping through special hoops.
And I don't think you can attach to macOS (Apple) processes with SIP enabled.

I gave up on running lldb as a sub-process (even after giving it permissions to attach, it causes lldb, debugserver, and Activity Monitor to hang with 100% CPU). Instead I use something like the above with /usr/bin/sample to get a backtrace when an assertion fails in my debug builds. (spindump must be run as root, so it is useless here)

forking lldb to get a complete backtrace
 
 
Q