diff --git a/i/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm --- a/i/lldb/source/Host/macosx/objcxx/Host.mm +++ b/lldb/source/Host/macosx/objcxx/Host.mm @@ -144,42 +144,22 @@ ::memset(pid_str, 0, sizeof(pid_str)); ConnectionStatus status; const size_t pid_str_len = file_conn.Read( - pid_str, sizeof(pid_str), std::chrono::seconds(0), status, NULL); + pid_str, sizeof(pid_str), std::chrono::seconds(5), status, NULL); if (pid_str_len > 0) { int pid = atoi(pid_str); + + // The inferior sends its pid right before it calls posix_spawn. + // We want to wait a tiny bit for the next process to get + // started, and stop at dyld_start, before we attach. + const int short_sleep = 100000; // 0.1 seconds + ::usleep(short_sleep); + return (void *)(intptr_t)pid; } } return NULL; } -static bool WaitForProcessToSIGSTOP(const lldb::pid_t pid, - const int timeout_in_seconds) { - const int time_delta_usecs = 100000; - const int num_retries = timeout_in_seconds / time_delta_usecs; - for (int i = 0; i < num_retries; i++) { - struct proc_bsdinfo bsd_info; - int error = ::proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &bsd_info, - PROC_PIDTBSDINFO_SIZE); - - switch (error) { - case EINVAL: - case ENOTSUP: - case ESRCH: - case EPERM: - return false; - - default: - break; - - case 0: - if (bsd_info.pbi_status == SSTOP) - return true; - } - ::usleep(time_delta_usecs); - } - return false; -} #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) const char *applscript_in_new_tty = "tell application \"Terminal\"\n" @@ -323,15 +303,9 @@ thread_result_t accept_thread_result = NULL; lldb_error = accept_thread->Join(&accept_thread_result); - if (lldb_error.Success() && accept_thread_result) { + if (lldb_error.Success() && accept_thread_result) pid = (intptr_t)accept_thread_result; - // Wait for process to be stopped at the entry point by watching - // for the process status to be set to SSTOP which indicates it it - // SIGSTOP'ed at the entry point - WaitForProcessToSIGSTOP(pid, 5); - } - llvm::sys::fs::remove(unix_socket_name); [applescript release]; if (pid != LLDB_INVALID_PROCESS_ID) diff --git a/i/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp --- a/i/lldb/tools/darwin-debug/darwin-debug.cpp +++ b/lldb/tools/darwin-debug/darwin-debug.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -97,7 +99,7 @@ pid_t posix_spawn_for_debug(char *const *argv, char *const *envp, const char *working_dir, cpu_type_t cpu_type, - int disable_aslr) { + int disable_aslr, int socket_fd) { pid_t pid = 0; const char *path = argv[0]; @@ -147,6 +149,29 @@ if (working_dir) ::chdir(working_dir); + // We were able to connect to the socket, now write our PID so whomever + // launched us will know this process's ID + char pid_str[64]; + const int pid_str_len = + ::snprintf(pid_str, sizeof(pid_str), "%i", ::getpid()); + const int bytes_sent = ::send(socket_fd, pid_str, pid_str_len, 0); + + if (pid_str_len != bytes_sent) { + perror("error: send (socket_fd, pid_str, pid_str_len, 0)"); + exit(1); + } + + // Set the socket socket_fd marked as close-on-exec, leave + // it open for now. lldb might use this to detect when the + // exec has happened, and we can attach to the inferior + // safely. + errno = 0; + int opts = fcntl (socket_fd, F_GETFL); + if (errno == 0) { + opts = opts | O_CLOEXEC; + fcntl (socket_fd, F_SETFL, opts); + } + exit_with_errno(::posix_spawnp(&pid, path, NULL, &attr, (char *const *)argv, (char *const *)envp), "posix_spawn() error: "); @@ -290,21 +315,6 @@ exit(1); } - // We were able to connect to the socket, now write our PID so whomever - // launched us will know this process's ID - char pid_str[64]; - const int pid_str_len = - ::snprintf(pid_str, sizeof(pid_str), "%i", ::getpid()); - const int bytes_sent = ::send(s, pid_str, pid_str_len, 0); - - if (pid_str_len != bytes_sent) { - perror("error: send (s, pid_str, pid_str_len, 0)"); - exit(1); - } - - // We are done with the socket - close(s); - system("clear"); printf("Launching: '%s'\n", argv[0]); if (working_dir.empty()) { @@ -326,7 +336,8 @@ pass_env ? *_NSGetEnviron() : NULL, // Pass current environment as we may // have modified it if "--env" options // was used, do NOT pass "envp" here - working_dir.empty() ? NULL : working_dir.c_str(), cpu_type, disable_aslr); + working_dir.empty() ? NULL : working_dir.c_str(), cpu_type, disable_aslr, + s); return 0; }