#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#if defined(__linux__)
+#include <sys/prctl.h>
+#endif
#if defined(__ANDROID__)
#include <unwind.h>
if (GGML_NO_BACKTRACE) {
return;
}
- char attach[32];
- snprintf(attach, sizeof(attach), "attach %d", getpid());
- int pid = fork();
- if (pid == 0) {
+#if defined(__linux__)
+ FILE * f = fopen("/proc/self/status", "r");
+ size_t size = 0;
+ char * line = NULL;
+ ssize_t length = 0;
+ while ((length = getline(&line, &size, f)) > 0) {
+ if (!strncmp(line, "TracerPid:", sizeof("TracerPid:") - 1) &&
+ (length != sizeof("TracerPid:\t0\n") - 1 || line[length - 2] != '0')) {
+ // Already being debugged, and the breakpoint is the later abort()
+ free(line);
+ fclose(f);
+ return;
+ }
+ }
+ free(line);
+ fclose(f);
+ int lock[2] = { -1, -1 };
+ (void) !pipe(lock); // Don't start gdb until after PR_SET_PTRACER
+#endif
+ const int parent_pid = getpid();
+ const int child_pid = fork();
+ if (child_pid < 0) { // error
+ return;
+ } else if (child_pid == 0) { // child
+ char attach[32];
+ snprintf(attach, sizeof(attach), "attach %d", parent_pid);
+#if defined(__linux__)
+ close(lock[1]);
+ (void) !read(lock[0], lock, 1);
+#endif
// try gdb
execlp("gdb", "gdb", "--batch",
"-ex", "set style enabled on",
execlp("lldb", "lldb", "--batch",
"-o", "bt",
"-o", "quit",
- "-p", attach,
+ "-p", &attach[sizeof("attach ") - 1],
(char *) NULL);
- exit(EXIT_FAILURE);
- } else {
- int wstatus;
- waitpid(pid, &wstatus, 0);
- if (WIFEXITED(wstatus)) {
- if (WEXITSTATUS(wstatus) == EXIT_FAILURE) {
- // gdb failed, fallback to backtrace_symbols
- ggml_print_backtrace_symbols();
- }
- }
+ // gdb failed, fallback to backtrace_symbols
+ ggml_print_backtrace_symbols();
+ _Exit(0);
+ } else { // parent
+#if defined(__linux__)
+ prctl(PR_SET_PTRACER, child_pid);
+ close(lock[1]);
+ close(lock[0]);
+#endif
+ waitpid(child_pid, NULL, 0);
}
}
#else