[Lldb-commits] [lldb] r116841 - in /lldb/trunk: lldb.xcodeproj/project.pbxproj source/Host/macosx/Host.mm tools/darwin-debug/darwin-debug.cpp

Greg Clayton gclayton at apple.com
Tue Oct 19 11:15:50 PDT 2010


Author: gclayton
Date: Tue Oct 19 13:15:50 2010
New Revision: 116841

URL: http://llvm.org/viewvc/llvm-project?rev=116841&view=rev
Log:
Fixed all known race conditions with starting a process in a new terminal.
We now spawn a thread to accept a unix socket connection from the inferior
when it spawns in the terminal, then we launch the process, then we get
the pid back through the unix socket, and then wait for it to SIGSTOP.

darwin-debug now clears the terminal screen and prints out the program and
arguments that are about to be launched.


Modified:
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Host/macosx/Host.mm
    lldb/trunk/tools/darwin-debug/darwin-debug.cpp

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=116841&r1=116840&r2=116841&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Oct 19 13:15:50 2010
@@ -2490,6 +2490,7 @@
 			isa = PBXProject;
 			buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
 			compatibilityVersion = "Xcode 3.1";
+			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				en,

Modified: lldb/trunk/source/Host/macosx/Host.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Host.mm?rev=116841&r1=116840&r2=116841&view=diff
==============================================================================
--- lldb/trunk/source/Host/macosx/Host.mm (original)
+++ lldb/trunk/source/Host/macosx/Host.mm Tue Oct 19 13:15:50 2010
@@ -9,8 +9,10 @@
 
 #include "lldb/Host/Host.h"
 
-#include <sys/types.h>
+#include <libproc.h>
+#include <sys/proc.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/Communication.h"
@@ -159,79 +161,15 @@
     error = ::GetProcessPID(&psn, &pid);
     return pid;
 }
-#define LLDB_HOST_USE_APPLESCRIPT
-#if defined (LLDB_HOST_USE_APPLESCRIPT)
-
-lldb::pid_t
-Host::LaunchInNewTerminal 
-(
-    const char **argv, 
-    const char **envp,
-    const ArchSpec *arch_spec,
-    bool stop_at_entry,
-    bool disable_aslr
-)
-{
-    if (!argv || !argv[0])
-        return LLDB_INVALID_PROCESS_ID;
-    
-    std::string unix_socket_name;
-
-    char temp_file_path[PATH_MAX] = "/tmp/XXXXXX";    
-    if (::mktemp (temp_file_path) == NULL)
-        return LLDB_INVALID_PROCESS_ID;
-
-    unix_socket_name.assign (temp_file_path);
-    
-    StreamString command;
-    
-    FileSpec darwin_debug_file_spec;
-    if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
-        return LLDB_INVALID_PROCESS_ID;
-    darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
-        
-    if (!darwin_debug_file_spec.Exists())
-        return LLDB_INVALID_PROCESS_ID;
-    
-    char launcher_path[PATH_MAX];
-    darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
-    command.Printf ("tell application \"Terminal\"\n    do script \"'%s'", launcher_path);
-    
-    command.Printf(" --unix-socket=%s", unix_socket_name.c_str());
-
-    if (arch_spec && arch_spec->IsValid())
-    {
-        command.Printf(" --arch=%s", arch_spec->AsCString());
-    }
-
-    if (disable_aslr)
-    {
-        command.PutCString(" --disable-aslr");
-    }
-        
-    command.PutCString(" --");
-
-    if (argv)
-    {
-        for (size_t i=0; argv[i] != NULL; ++i)
-        {
-            command.Printf(" '%s'", argv[i]);
-        }
-    }
-    command.PutCString (" ; exit\"\nend tell\n");
-    const char *script_source = command.GetString().c_str();
-    NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]];
 
-    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
 
-    Error lldb_error;
-    // Sleep and wait a bit for debugserver to start to listen...
+static void *
+AcceptPIDFromInferior (void *arg)
+{
+    const char *connect_url = (const char *)arg;
     ConnectionFileDescriptor file_conn;
-    char connect_url[128];
-    ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
-
-    [applescript executeAndReturnError:nil];
-    if (file_conn.Connect(connect_url, &lldb_error) == eConnectionStatusSuccess)
+    Error error;
+    if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
     {
         char pid_str[256];
         ::bzero (pid_str, sizeof(pid_str));
@@ -239,18 +177,48 @@
         const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
         if (pid_str_len > 0)
         {
-            pid = atoi (pid_str);
-            // Sleep for a bit to allow the process to exec and stop at the entry point...
-            sleep(1);
+            int pid = atoi (pid_str);
+            return (void *)(intptr_t)pid;
         }
     }
-    [applescript release];
-    return pid;
+    return NULL;
 }
 
-#else
-lldb::pid_t
-Host::LaunchInNewTerminal 
+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;
+}
+
+static lldb::pid_t
+LaunchInNewTerminalWithCommandFile 
 (
     const char **argv, 
     const char **envp,
@@ -365,31 +333,158 @@
 
     Error lldb_error;
     // Sleep and wait a bit for debugserver to start to listen...
-    ConnectionFileDescriptor file_conn;
     char connect_url[128];
     ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
 
+    // Spawn a new thread to accept incoming connection on the connect_url
+    // so we can grab the pid from the inferior
+    lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(),
+                                                       AcceptPIDFromInferior,
+                                                       connect_url,
+                                                       &lldb_error);
+    
     ProcessSerialNumber psn;
     error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1);
     if (error == noErr)
     {
-        if (file_conn.Connect(connect_url, &lldb_error) == eConnectionStatusSuccess)
+        thread_result_t accept_thread_result = NULL;
+        if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error))
         {
-            char pid_str[256];
-            ::bzero (pid_str, sizeof(pid_str));
-            ConnectionStatus status;
-            const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
-            if (pid_str_len > 0)
+            if (accept_thread_result)
             {
-                pid = atoi (pid_str);
-                // Sleep for a bit to allow the process to exec and stop at the entry point...
-                sleep(1);
+                pid = (intptr_t)accept_thread_result;
+            
+                // Wait for process to be stopped the 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);
             }
         }
     }
+    else
+    {
+        Host::ThreadCancel (accept_thread, &lldb_error);
+    }
+
     return pid;
 }
+
+
+lldb::pid_t
+LaunchInNewTerminalWithAppleScript
+(
+    const char **argv, 
+    const char **envp,
+    const ArchSpec *arch_spec,
+    bool stop_at_entry,
+    bool disable_aslr
+)
+{
+    if (!argv || !argv[0])
+        return LLDB_INVALID_PROCESS_ID;
+    
+    std::string unix_socket_name;
+
+    char temp_file_path[PATH_MAX] = "/tmp/XXXXXX";    
+    if (::mktemp (temp_file_path) == NULL)
+        return LLDB_INVALID_PROCESS_ID;
+
+    unix_socket_name.assign (temp_file_path);
+    
+    StreamString command;
+    
+    FileSpec darwin_debug_file_spec;
+    if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
+        return LLDB_INVALID_PROCESS_ID;
+    darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
+        
+    if (!darwin_debug_file_spec.Exists())
+        return LLDB_INVALID_PROCESS_ID;
+    
+    char launcher_path[PATH_MAX];
+    darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
+    command.Printf ("tell application \"Terminal\"\n    do script \"'%s'", launcher_path);
+    
+    command.Printf(" --unix-socket=%s", unix_socket_name.c_str());
+
+    if (arch_spec && arch_spec->IsValid())
+    {
+        command.Printf(" --arch=%s", arch_spec->AsCString());
+    }
+
+    if (disable_aslr)
+    {
+        command.PutCString(" --disable-aslr");
+    }
+        
+    command.PutCString(" --");
+
+    if (argv)
+    {
+        for (size_t i=0; argv[i] != NULL; ++i)
+        {
+            command.Printf(" '%s'", argv[i]);
+        }
+    }
+    command.PutCString (" ; echo Process exited with status $?\"\nend tell\n");
+    const char *script_source = command.GetString().c_str();
+    NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]];
+
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+    Error lldb_error;
+    // Sleep and wait a bit for debugserver to start to listen...
+    ConnectionFileDescriptor file_conn;
+    char connect_url[128];
+    ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
+
+    // Spawn a new thread to accept incoming connection on the connect_url
+    // so we can grab the pid from the inferior
+    lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(),
+                                                       AcceptPIDFromInferior,
+                                                       connect_url,
+                                                       &lldb_error);
+    
+
+    [applescript executeAndReturnError:nil];
+    
+    thread_result_t accept_thread_result = NULL;
+    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error))
+    {
+        if (accept_thread_result)
+        {
+            pid = (intptr_t)accept_thread_result;
+        
+            // Wait for process to be stopped the 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);
+        }
+    }
+    [applescript release];
+    return pid;
+}
+
+
+#define LLDB_HOST_USE_APPLESCRIPT
+
+lldb::pid_t
+Host::LaunchInNewTerminal 
+(
+    const char **argv, 
+    const char **envp,
+    const ArchSpec *arch_spec,
+    bool stop_at_entry,
+    bool disable_aslr
+)
+{
+#if defined (LLDB_HOST_USE_APPLESCRIPT)
+    return LaunchInNewTerminalWithAppleScript (argv, envp, arch_spec, stop_at_entry, disable_aslr);
+#else
+    return LaunchInNewTerminalWithCommandFile (argv, envp, arch_spec, stop_at_entry, disable_aslr);
 #endif
+}
+
 
 bool
 Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)

Modified: lldb/trunk/tools/darwin-debug/darwin-debug.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/darwin-debug/darwin-debug.cpp?rev=116841&r1=116840&r2=116841&view=diff
==============================================================================
--- lldb/trunk/tools/darwin-debug/darwin-debug.cpp (original)
+++ lldb/trunk/tools/darwin-debug/darwin-debug.cpp Tue Oct 19 13:15:50 2010
@@ -253,6 +253,11 @@
     // We are done with the socket
     close (s);
 
+    system("clear");
+    printf ("Launching '%s' for debug with %u arguments:\n", argv[0], argc);
+    for (int i=0; i<argc; ++i)
+        printf ("argv[%u] = '%s'\n", i, argv[i]);
+
     // Now we posix spawn to exec this process into the inferior that we want
     // to debug.
     posix_spawn_for_debug (argv, 





More information about the lldb-commits mailing list