+static int backtrace_string_index = 3;
+static int backtrace_done = 0;
+
+/*
+ * Attach gdb to pid_parent and dump a backtrace to i3-backtrace.$pid in the
+ * tmpdir
+ */
+static int backtrace(void) {
+ char *tmpdir = getenv("TMPDIR");
+ if (tmpdir == NULL)
+ tmpdir = "/tmp";
+
+ pid_t pid_parent = getpid();
+
+ char *filename = NULL;
+ int suffix = 0;
+ struct stat bt;
+ /* Find a unique filename for the backtrace (since the PID of i3 stays the
+ * same), so that we don’t overwrite earlier backtraces. */
+ do {
+ FREE(filename);
+ sasprintf(&filename, "%s/i3-backtrace.%d.%d.txt", tmpdir, pid_parent, suffix);
+ suffix++;
+ } while (stat(filename, &bt) == 0);
+
+ pid_t pid_gdb = fork();
+ if (pid_gdb < 0) {
+ DLOG("Failed to fork for GDB\n");
+ return -1;
+ } else if (pid_gdb == 0) {
+ /* child */
+ int stdin_pipe[2],
+ stdout_pipe[2];
+
+ if (pipe(stdin_pipe) == -1) {
+ ELOG("Failed to init stdin_pipe\n");
+ return -1;
+ }
+ if (pipe(stdout_pipe) == -1) {
+ ELOG("Failed to init stdout_pipe\n");
+ return -1;
+ }
+
+ /* close standard streams in case i3 is started from a terminal; gdb
+ * needs to run without controlling terminal for it to work properly in
+ * this situation */
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ /* We provide pipe file descriptors for stdin/stdout because gdb < 7.5
+ * crashes otherwise, see
+ * http://sourceware.org/bugzilla/show_bug.cgi?id=14114 */
+ dup2(stdin_pipe[0], STDIN_FILENO);
+ dup2(stdout_pipe[1], STDOUT_FILENO);
+
+ char *pid_s, *gdb_log_cmd;
+ sasprintf(&pid_s, "%d", pid_parent);
+ sasprintf(&gdb_log_cmd, "set logging file %s", filename);
+
+ char *args[] = {
+ "gdb",
+ start_argv[0],
+ "-p",
+ pid_s,
+ "-batch",
+ "-nx",
+ "-ex", gdb_log_cmd,
+ "-ex", "set logging on",
+ "-ex", "bt full",
+ "-ex", "quit",
+ NULL};
+ execvp(args[0], args);
+ DLOG("Failed to exec GDB\n");
+ exit(1);
+ }
+ int status = 0;
+
+ waitpid(pid_gdb, &status, 0);
+
+ /* see if the backtrace was successful or not */
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ DLOG("GDB did not run properly\n");
+ return -1;
+ } else if (stat(filename, &bt) == -1) {
+ DLOG("GDB executed successfully, but no backtrace was generated\n");
+ return -1;
+ }
+ return 1;
+}