[lldb-dev] Linux/Posix spawning, signal masking

Todd Fiala tfiala at google.com
Wed Jan 22 13:45:32 PST 2014


So I just about have this done (the original 3 steps, not switching to
fork()/exec()).

One thing I hit was an area I noticed yesterday: on Linux (x86_64, Ubuntu
12.04), I'm finding that I need to *not* take defaults for all the signal
handlers in lldb-gdbserver; otherwise, the target process never starts
operating.  Technically the target process is exiting immediately with an
exit_state of 127 with signal = 0.

For the moment, I have that #ifdef'd in the Apple/Linux/FreeBSD
LaunchProcessPosixSpawn method so that only Linux doesn't reset the child
signal handlers to defaults.  I'm thinking the FreeBSD/Apple BSD lineage
might behave more similarly here as my first stake in the sand for a guess,
but that would be changing behavior for FreeBSD.  (Ed - any thoughts here?
 I could just as well flip the #if defined(__linux__) to #if
!defined(__APPLE__).)  Ultimately the root cause of this is not clear to me
yet.

For the directory handling, I'm having that handled via __pthread* methods
on Apple and continuing to do what it did before on everything else.  I'll
look into the fork()/exec() option as a follow up after I work through some
of the more obviously broken bits of lldb-gdbserver.

See below for the current state of the patch.  I'm about to run tests on
Ubuntu and try a build and tests on my MBP.

-Todd


On Wed, Jan 22, 2014 at 10:24 AM, Greg Clayton <gclayton at apple.com> wrote:

> You might need to add "#if defined(__APPLE__)" around the calls to
> __pthread_chdir and __pthread_fchdir. Those might be darwin specific.
>
> There is no way to set your current working directory when using
> posix_spawn, so to work around this, we change directory in a thread
> specific way by calling __pthread_chdir(working_dir) and reverting it using
> __pthread_fchdir(-1), so as to not hose over the process that has the lldb
> shared library loaded by changing the global working directory.
>
> So in order to eventually fix being able to obey the launch flag
> eLaunchFlagDebug and also to be able to set the working directory, non
> darwin builds might need to change over to using fork()/exec() since after
> the fork the child process can set its working directory and also call
> ptrace() to start being debuggable and then calling exec(). When ptrace()
> has been called to allow the process to be debugged, I believe it stops
> right at the entry point upon exec. Again, this would be for non-darwin
> builds since Apple has a posix_spawn flag of POSIX_SPAWN_START_SUSPENDED
> that can be set to enforce stopping at the entry point and also has the
> thread specific way to change directory.
>
> Greg
>
>
> On Jan 22, 2014, at 10:00 AM, Todd Fiala <tfiala at google.com> wrote:
>
> > Correct.
> >
> >
> > On Wed, Jan 22, 2014 at 9:55 AM, Greg Clayton <gclayton at apple.com>
> wrote:
> > So the fix will be:
> > 1 - Remove LaunchProcessPosixSpawn() from Host.mm
> > 2 - Copy it over into Host.cpp
> > 3 - Make sure LaunchProcessPosixSpawn is compiled for Apple builds as
> well in Host.cpp
> >
> > Right?
> >
> >
> > On Jan 22, 2014, at 9:54 AM, Todd Fiala <tfiala at google.com> wrote:
> >
> > > > It is indeed the right fix.
> > >
> > > Ok - I'll take care of that part.  Thanks!
> > >
> > >
> > > On Wed, Jan 22, 2014 at 9:52 AM, Greg Clayton <gclayton at apple.com>
> wrote:
> > > It is indeed the right fix. Host.mm has a mac specific version which
> does this:
> > >
> > >     sigset_t no_signals;
> > >     sigset_t all_signals;
> > >     sigemptyset (&no_signals);
> > >     sigfillset (&all_signals);
> > >     ::posix_spawnattr_setsigmask(&attr, &no_signals);
> > >     ::posix_spawnattr_setsigdefault(&attr, &all_signals);
> > >
> > > Compared to the incorrect version you noticed in Host.cpp:
> > >
> > >     sigset_t no_signals;
> > >     sigset_t all_signals;
> > >     sigemptyset (&no_signals);
> > >     sigfillset (&all_signals);
> > >     ::posix_spawnattr_setsigmask(&attr, &all_signals);
> > >     ::posix_spawnattr_setsigdefault(&attr, &no_signals);
> > >
> > > (notice all_signals and no_signals are reversed in the last two
> function calls in Host.cpp.
> > >
> > > You might compare the "LaunchProcessPosixSpawn" in Host.mm and try and
> just copy it to Host.cpp and see if it works. I can't find anything darwin
> specific in the code after a quick glance and we have used the Host.mm
> LaunchProcessPosixSpawn() for a few years now, so it is definitely tested...
> > >
> > > So the fix would seem to be:
> > > 1 - Remove LaunchProcessPosixSpawn() from Host.mm
> > > 2 - Copy it over into Host.cpp
> > > 3 - Make sure LaunchProcessPosixSpawn is compiled for Apple builds as
> well in Host.cpp
> > >
> > >
> > > On Jan 21, 2014, at 10:49 PM, Todd Fiala <tfiala at google.com> wrote:
> > >
> > > > Hi all,
> > > >
> > > > In source/Host/common/Host.cpp, there is a posix process spawning
> method called LaunchProcessPosixSpawn.  On my Linux system, it is used to
> start the target process in lldb-gdbserver.  It looks like FreeBSD uses it
> as well.  Most of the Platform launchers appear to funnel to it as well
> (via Host::LaunchProcess ()).
> > > >
> > > > There is a section of code in LaunchProcessPosixSpawn that masks all
> signals for the child process that is started up:
> > > >
> > > > ::posix_spawnattr_setsigmask(&attr, &all_signals)
> > > >
> > > > When that is set, it seems to be preventing the child from receiving
> everything except the non-blockable signals.  This has the effect of (at
> the very least) blocking SIGINT (i.e. ^C from the keyboard) and SIGTERM
> (standard unadorned "kill pid").  This appears to be the cause of a few
> bugs as I try to get lldb-gdbserver working on Linux.  For example:
> > > >
> > > > 1. hitting ^C on an lldb-gdbserver that spawned a debuggee target
> process would kill the lldb-gdbserver, but not the debuggee target, which
> continues to run.
> > > >
> > > > 2. sending a SIGTERM (kill {debuggee pid}) while it is getting
> debugged and running is ignored.
> > > >
> > > > 3. sending a SIGTERM to the debuggee after issue #1 (where
> lldb-gdbserver is no longer running) is ignored.
> > > >
> > > > 4. killing lldb-gdbserver from an attached lldb that shuts down and
> kills the remote does indeed kill lldb-gebserver, but does not kill the
> target process.
> > > >
> > > > (Of course sending a 'kill -9 {debuggee pid}' works fine to kill the
> target process).
> > > >
> > > >
> > > > I've modified this method locally to not mask any signals:
> > > >
> > > > ::posix_spawnattr_setsigmask (&attr, &no_signals)
> > > >
> > > > This seems to address all the problems I had above for
> lldb-gdbserver as signals propagate properly, and the target responds
> correctly to signals sent when the parent dies, etc.
> > > >
> > > > I've also run all the existing tests (on my system, that amounts to
> 275 tests that really run), and those are all passing.
> > > >
> > > > However, given that so much code flows through here (or at least
> appears to) that is not directly related to the lldb-gdbserver --- i.e.
> local linux/FreeBSD debugging --- I'm highly skeptical that this is the
> right fix.  I did try using local debugging with lldb with my change in
> place, and that seemed to work fine.  But I'm thinking that perhaps the
> signal blocking was intended and that behavior is needed in some cases that
> (perhaps) are not covered by tests that run on Linux.
> > > >
> > > > Any thoughts on why all the signals were getting masked on process
> spawning?  Does that change look okay as is?
> > > >
> > > > Thanks!
> > > >
> > > > Sincerely,
> > > > Todd Fiala
> > > > _______________________________________________
> > > > lldb-dev mailing list
> > > > lldb-dev at cs.uiuc.edu
> > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> > >
> > >
> > >
> > >
> > > --
> > > Todd Fiala |   Software Engineer |     tfiala at google.com |
> 650-943-3180
> > >
> >
> >
> >
> >
> > --
> > Todd Fiala |   Software Engineer |     tfiala at google.com |
> 650-943-3180
> >
>
>


-- 
Todd Fiala | Software Engineer | tfiala at google.com | 650-943-3180
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140122/c8d6a00c/attachment.html>
-------------- next part --------------
Index: source/Host/common/Host.cpp
===================================================================
--- source/Host/common/Host.cpp	(revision 199814)
+++ source/Host/common/Host.cpp	(working copy)
@@ -1637,10 +1637,234 @@
     return error;
 }
 
+
+// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC
+// systems
+
+#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__)
+
+static Error
+LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
+{
+    Error error;
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+
+    posix_spawnattr_t attr;
+    error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
+
+    if (error.Fail() || log)
+        error.PutToLog(log, "::posix_spawnattr_init ( &attr )");
+    if (error.Fail())
+        return error;
+
+    // Make a quick class that will cleanup the posix spawn attributes in case
+    // we return in the middle of this function.
+    lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
+
+    sigset_t no_signals;
+    sigset_t all_signals;
+    sigemptyset (&no_signals);
+    sigfillset (&all_signals);
+    ::posix_spawnattr_setsigmask(&attr, &no_signals);
+#if defined(__linux__)
+    ::posix_spawnattr_setsigdefault(&attr, &no_signals);
+#else
+    ::posix_spawnattr_setsigdefault(&attr, &all_signals);
+#endif
+
+    // TODO: consider hoisting GetPosixspawnFlags into common/Host.cpp
+#if defined(__APPLE__)
+    short flags = GetPosixspawnFlags(launch_info);
+#else
+    short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
+#endif
+
+    error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
+    if (error.Fail() || log)
+        error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
+    if (error.Fail())
+        return error;
+
+    // posix_spawnattr_setbinpref_np appears to be an Apple extension per:
+    // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/
+#if defined(__APPLE__) && !defined(__arm__)
+
+    // We don't need to do this for ARM, and we really shouldn't now that we
+    // have multiple CPU subtypes and no posix_spawnattr call that allows us
+    // to set which CPU subtype to launch...
+    const ArchSpec &arch_spec = launch_info.GetArchitecture();
+    cpu_type_t cpu = arch_spec.GetMachOCPUType();
+    if (cpu != 0 &&
+        cpu != UINT32_MAX &&
+        cpu != LLDB_INVALID_CPUTYPE)
+    {
+        size_t ocount = 0;
+        error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
+        if (error.Fail() || log)
+            error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount);
+
+        if (error.Fail() || ocount != 1)
+            return error;
+    }
+
+#endif
+
+    const char *tmp_argv[2];
+    char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
+    char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+    if (argv == NULL)
+    {
+        // posix_spawn gets very unhappy if it doesn't have at least the program
+        // name in argv[0]. One of the side affects I have noticed is the environment
+        // variables don't make it into the child process if "argv == NULL"!!!
+        tmp_argv[0] = exe_path;
+        tmp_argv[1] = NULL;
+        argv = (char * const*)tmp_argv;
+    }
+
+#if !defined(__APPLE__)
+    // manage the working directory
+    char current_dir[PATH_MAX];
+    current_dir[0] = '\0';
+#endif
+
+    const char *working_dir = launch_info.GetWorkingDirectory();
+    if (working_dir)
+    {
+#if defined(__APPLE__)
+        // No more thread specific current working directory
+        if (__pthread_chdir (working_dir) < 0) {
+            if (errno == ENOENT) {
+                error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
+            } else if (errno == ENOTDIR) {
+                error.SetErrorStringWithFormat("Path doesn't name a directory: %s", working_dir);
+            } else {
+                error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution.");
+            }
+            return error;
+        }
+#else
+        if (::getcwd(current_dir, sizeof(current_dir)) == NULL)
+        {
+            error.SetError(errno, eErrorTypePOSIX);
+            error.LogIfError(log, "unable to save the current directory");
+            return error;
+        }
+
+        if (::chdir(working_dir) == -1)
+        {
+            error.SetError(errno, eErrorTypePOSIX);
+            error.LogIfError(log, "unable to change working directory to %s", working_dir);
+            return error;
+        }
+#endif
+    }
+
+    const size_t num_file_actions = launch_info.GetNumFileActions ();
+    if (num_file_actions > 0)
+    {
+        posix_spawn_file_actions_t file_actions;
+        error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
+        if (error.Fail() || log)
+            error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )");
+        if (error.Fail())
+            return error;
+
+        // Make a quick class that will cleanup the posix spawn attributes in case
+        // we return in the middle of this function.
+        lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy);
+
+        for (size_t i=0; i<num_file_actions; ++i)
+        {
+            const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
+            if (launch_file_action)
+            {
+                if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
+                                                                             launch_file_action,
+                                                                             log,
+                                                                             error))
+                    return error;
+            }
+        }
+
+        error.SetError (::posix_spawnp (&pid,
+                                        exe_path,
+                                        &file_actions,
+                                        &attr,
+                                        argv,
+                                        envp),
+                        eErrorTypePOSIX);
+
+        if (error.Fail() || log)
+        {
+            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
+                           pid,
+                           exe_path,
+                           &file_actions,
+                           &attr,
+                           argv,
+                           envp);
+            if (log)
+            {
+                for (int ii=0; argv[ii]; ++ii)
+                    log->Printf("argv[%i] = '%s'", ii, argv[ii]);
+            }
+        }
+
+    }
+    else
+    {
+        error.SetError (::posix_spawnp (&pid,
+                                        exe_path,
+                                        NULL,
+                                        &attr,
+                                        argv,
+                                        envp),
+                        eErrorTypePOSIX);
+
+        if (error.Fail() || log)
+        {
+            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
+                           pid,
+                           exe_path,
+                           &attr,
+                           argv,
+                           envp);
+            if (log)
+            {
+                for (int ii=0; argv[ii]; ++ii)
+                    log->Printf("argv[%i] = '%s'", ii, argv[ii]);
+            }
+        }
+    }
+
+    if (working_dir)
+    {
+#if defined(__APPLE__)
+        // No more thread specific current working directory
+        __pthread_fchdir (-1);
+#else
+        if (::chdir(current_dir) == -1 && error.Success())
+        {
+            error.SetError(errno, eErrorTypePOSIX);
+            error.LogIfError(log, "unable to change current directory back to %s",
+                    current_dir);
+        }
+#endif
+    }
+
+    return error;
+}
+
+#endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems
+
+
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__)
 // The functions below implement process launching via posix_spawn() for Linux
 // and FreeBSD.
 
+#if 0 // ignore this implementation
+
 // The posix_spawn() and posix_spawnp() functions first appeared in FreeBSD 8.0,
 static Error
 LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
@@ -1663,10 +1887,9 @@
     lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
 
     sigset_t no_signals;
-    sigset_t all_signals;
     sigemptyset (&no_signals);
-    sigfillset (&all_signals);
-    ::posix_spawnattr_setsigmask(&attr, &all_signals);
+
+    ::posix_spawnattr_setsigmask(&attr, &no_signals);
     ::posix_spawnattr_setsigdefault(&attr, &no_signals);
 
     short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
@@ -1764,7 +1987,9 @@
     return error;
 }
 
+#endif // ignore implementation - pulling in Apple version
 
+
 Error
 Host::LaunchProcess (ProcessLaunchInfo &launch_info)
 {
@@ -1815,6 +2040,8 @@
         // If all went well, then set the process ID into the launch info
         launch_info.SetProcessID(pid);
 
+        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
         // Make sure we reap any processes we spawn or we will have zombies.
         if (!launch_info.MonitorProcess())
         {
@@ -1823,7 +2050,14 @@
                                          NULL,
                                          pid,
                                          monitor_signals);
+            if (log)
+                log->PutCString ("monitored child process with default Process::SetProcessExitStatus.");
         }
+        else
+        {
+            if (log)
+                log->PutCString ("monitored child process with user-specified process monitor.");
+        }
     }
     else
     {
Index: source/Host/macosx/Host.mm
===================================================================
--- source/Host/macosx/Host.mm	(revision 199814)
+++ source/Host/macosx/Host.mm	(working copy)
@@ -1586,176 +1586,6 @@
 #endif
 }
 
-static Error
-LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
-{
-    Error error;
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
-    
-    posix_spawnattr_t attr;
-    error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
-    
-    if (error.Fail() || log)
-        error.PutToLog(log, "::posix_spawnattr_init ( &attr )");
-    if (error.Fail())
-        return error;
-
-    // Make a quick class that will cleanup the posix spawn attributes in case
-    // we return in the middle of this function.
-    lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
-    
-    sigset_t no_signals;
-    sigset_t all_signals;
-    sigemptyset (&no_signals);
-    sigfillset (&all_signals);
-    ::posix_spawnattr_setsigmask(&attr, &no_signals);
-    ::posix_spawnattr_setsigdefault(&attr, &all_signals);
-
-    short flags = GetPosixspawnFlags(launch_info);
-    error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
-    if (error.Fail() || log)
-        error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
-    if (error.Fail())
-        return error;
-    
-#if !defined(__arm__)
-    
-    // We don't need to do this for ARM, and we really shouldn't now that we
-    // have multiple CPU subtypes and no posix_spawnattr call that allows us
-    // to set which CPU subtype to launch...
-    const ArchSpec &arch_spec = launch_info.GetArchitecture();
-    cpu_type_t cpu = arch_spec.GetMachOCPUType();
-    if (cpu != 0 && 
-        cpu != UINT32_MAX && 
-        cpu != LLDB_INVALID_CPUTYPE)
-    {
-        size_t ocount = 0;
-        error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
-        if (error.Fail() || log)
-            error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount);
-        
-        if (error.Fail() || ocount != 1)
-            return error;
-    }
-    
-#endif
-    
-    const char *tmp_argv[2];
-    char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
-    char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
-    if (argv == NULL)
-    {
-        // posix_spawn gets very unhappy if it doesn't have at least the program
-        // name in argv[0]. One of the side affects I have noticed is the environment
-        // variables don't make it into the child process if "argv == NULL"!!!
-        tmp_argv[0] = exe_path;
-        tmp_argv[1] = NULL;
-        argv = (char * const*)tmp_argv;
-    }
-
-    const char *working_dir = launch_info.GetWorkingDirectory();
-    if (working_dir)
-    {
-        // No more thread specific current working directory
-        if (__pthread_chdir (working_dir) < 0) {
-            if (errno == ENOENT) {
-                error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
-            } else if (errno == ENOTDIR) {
-                error.SetErrorStringWithFormat("Path doesn't name a directory: %s", working_dir);
-            } else {
-                error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution.");
-            }
-            return error;
-        }
-    }
-    
-    const size_t num_file_actions = launch_info.GetNumFileActions ();
-    if (num_file_actions > 0)
-    {
-        posix_spawn_file_actions_t file_actions;
-        error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
-        if (error.Fail() || log)
-            error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )");
-        if (error.Fail())
-            return error;
-
-        // Make a quick class that will cleanup the posix spawn attributes in case
-        // we return in the middle of this function.
-        lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy);
-
-        for (size_t i=0; i<num_file_actions; ++i)
-        {
-            const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
-            if (launch_file_action)
-            {
-                if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
-                                                                             launch_file_action,
-                                                                             log,
-                                                                             error))
-                    return error;
-            }
-        }
-        
-        error.SetError (::posix_spawnp (&pid, 
-                                        exe_path, 
-                                        &file_actions, 
-                                        &attr, 
-                                        argv,
-                                        envp),
-                        eErrorTypePOSIX);
-
-        if (error.Fail() || log)
-        {
-            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
-                           pid, 
-                           exe_path, 
-                           &file_actions, 
-                           &attr, 
-                           argv, 
-                           envp);
-            if (log)
-            {
-                for (int ii=0; argv[ii]; ++ii)
-                    log->Printf("argv[%i] = '%s'", ii, argv[ii]);
-            }
-        }
-
-    }
-    else
-    {
-        error.SetError (::posix_spawnp (&pid, 
-                                        exe_path, 
-                                        NULL, 
-                                        &attr, 
-                                        argv,
-                                        envp),
-                        eErrorTypePOSIX);
-
-        if (error.Fail() || log)
-        {
-            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
-                           pid, 
-                           exe_path, 
-                           &attr, 
-                           argv, 
-                           envp);
-            if (log)
-            {
-                for (int ii=0; argv[ii]; ++ii)
-                    log->Printf("argv[%i] = '%s'", ii, argv[ii]);
-            }
-        }
-    }
-    
-    if (working_dir)
-    {
-        // No more thread specific current working directory
-        __pthread_fchdir (-1);
-    }
-    
-    return error;
-}
-
 static bool
 ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info)
 {


More information about the lldb-dev mailing list