diff options
| author | Ed Maste <emaste@FreeBSD.org> | 2014-02-18 16:23:10 +0000 | 
|---|---|---|
| committer | Ed Maste <emaste@FreeBSD.org> | 2014-02-18 16:23:10 +0000 | 
| commit | 866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec (patch) | |
| tree | 95cb16075f0af1b3a05b9b84eb18dda8e6c903e9 /source/Host/common/Host.cpp | |
| parent | de889deb2c386f2a7831befaf226e5c86685fa53 (diff) | |
Notes
Diffstat (limited to 'source/Host/common/Host.cpp')
| -rw-r--r-- | source/Host/common/Host.cpp | 418 | 
1 files changed, 325 insertions, 93 deletions
| diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 262776f6c7190..9e5e4cbdb04aa 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -18,6 +18,7 @@  #include <winsock2.h>  #include <WS2tcpip.h>  #else +#include <unistd.h>  #include <dlfcn.h>  #include <grp.h>  #include <netdb.h> @@ -37,7 +38,7 @@  #include <AvailabilityMacros.h>  #endif -#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) +#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)  #include <spawn.h>  #include <sys/wait.h>  #include <sys/syscall.h> @@ -68,6 +69,18 @@  #include "llvm/Support/Host.h"  #include "llvm/Support/raw_ostream.h" +#if defined (__APPLE__) +#ifndef _POSIX_SPAWN_DISABLE_ASLR +#define _POSIX_SPAWN_DISABLE_ASLR       0x0100 +#endif + +extern "C" +{ +    int __pthread_chdir(const char *path); +    int __pthread_fchdir (int fildes); +} + +#endif  using namespace lldb;  using namespace lldb_private; @@ -367,25 +380,31 @@ Host::GetArchitecture (SystemDefaultArchitecture arch_kind)          // If the OS is Linux, "unknown" in the vendor slot isn't what we want          // for the default triple.  It's probably an artifact of config.guess.          if (triple.getOS() == llvm::Triple::Linux && triple.getVendor() == llvm::Triple::UnknownVendor) -            triple.setVendorName(""); +            triple.setVendorName (""); + +        const char* distribution_id = GetDistributionId ().AsCString();          switch (triple.getArch())          {          default:              g_host_arch_32.SetTriple(triple); +            g_host_arch_32.SetDistributionId (distribution_id);              g_supports_32 = true;              break;          case llvm::Triple::x86_64:              g_host_arch_64.SetTriple(triple); +            g_host_arch_64.SetDistributionId (distribution_id);              g_supports_64 = true;              g_host_arch_32.SetTriple(triple.get32BitArchVariant()); +            g_host_arch_32.SetDistributionId (distribution_id);              g_supports_32 = true;              break;          case llvm::Triple::sparcv9:          case llvm::Triple::ppc64:              g_host_arch_64.SetTriple(triple); +            g_host_arch_64.SetDistributionId (distribution_id);              g_supports_64 = true;              break;          } @@ -445,6 +464,19 @@ Host::GetTargetTriple()      return g_host_triple;  } +// See linux/Host.cpp for Linux-based implementations of this. +// Add your platform-specific implementation to the appropriate host file. +#if !defined(__linux__) + +const ConstString & +    Host::GetDistributionId () +{ +    static ConstString s_distribution_id; +    return s_distribution_id; +} + +#endif // #if !defined(__linux__) +  lldb::pid_t  Host::GetCurrentProcessID()  { @@ -457,7 +489,7 @@ lldb::tid_t  Host::GetCurrentThreadID()  {  #if defined (__APPLE__) -    // Calling "mach_port_deallocate()" bumps the reference count on the thread +    // Calling "mach_thread_self()" bumps the reference count on the thread      // port, so we need to deallocate it. mach_task_self() doesn't bump the ref      // count.      thread_port_t thread_self = mach_thread_self(); @@ -489,10 +521,14 @@ Host::GetSignalAsCString (int signo)      case SIGILL:    return "SIGILL";    // 4    illegal instruction (not reset when caught)      case SIGTRAP:   return "SIGTRAP";   // 5    trace trap (not reset when caught)      case SIGABRT:   return "SIGABRT";   // 6    abort() -#if  (defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE)) +#if  defined(SIGPOLL) +#if !defined(SIGIO) || (SIGPOLL != SIGIO) +// Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to +// fail with 'multiple define cases with same value'      case SIGPOLL:   return "SIGPOLL";   // 7    pollable event ([XSR] generated, not supported)  #endif -#if  !defined(_POSIX_C_SOURCE) +#endif +#if  defined(SIGEMT)      case SIGEMT:    return "SIGEMT";    // 7    EMT instruction  #endif      case SIGFPE:    return "SIGFPE";    // 8    floating point exception @@ -510,15 +546,17 @@ Host::GetSignalAsCString (int signo)      case SIGCHLD:   return "SIGCHLD";   // 20    to parent on child stop or exit      case SIGTTIN:   return "SIGTTIN";   // 21    to readers pgrp upon background tty read      case SIGTTOU:   return "SIGTTOU";   // 22    like TTIN for output if (tp->t_local<OSTOP) -#if  !defined(_POSIX_C_SOURCE) +#if  defined(SIGIO)      case SIGIO:     return "SIGIO";     // 23    input/output possible signal  #endif      case SIGXCPU:   return "SIGXCPU";   // 24    exceeded CPU time limit      case SIGXFSZ:   return "SIGXFSZ";   // 25    exceeded file size limit      case SIGVTALRM: return "SIGVTALRM"; // 26    virtual time alarm      case SIGPROF:   return "SIGPROF";   // 27    profiling time alarm -#if  !defined(_POSIX_C_SOURCE) +#if  defined(SIGWINCH)      case SIGWINCH:  return "SIGWINCH";  // 28    window size changes +#endif +#if  defined(SIGINFO)      case SIGINFO:   return "SIGINFO";   // 29    information request  #endif      case SIGUSR1:   return "SIGUSR1";   // 30    user defined signal 1 @@ -739,8 +777,8 @@ bool  Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,                            const char *thread_name, size_t len)  { -    char *namebuf = (char *)::malloc (len + 1); - +    std::unique_ptr<char[]> namebuf(new char[len+1]); +          // Thread names are coming in like '<lldb.comm.debugger.edit>' and      // '<lldb.comm.debugger.editline>'.  So just chopping the end of the string      // off leads to a lot of similar named threads.  Go through the thread name @@ -749,10 +787,10 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,      if (lastdot && lastdot != thread_name)          thread_name = lastdot + 1; -    ::strncpy (namebuf, thread_name, len); +    ::strncpy (namebuf.get(), thread_name, len);      namebuf[len] = 0; -    int namebuflen = strlen(namebuf); +    int namebuflen = strlen(namebuf.get());      if (namebuflen > 0)      {          if (namebuf[namebuflen - 1] == '(' || namebuf[namebuflen - 1] == '>') @@ -761,10 +799,8 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,              namebuflen--;              namebuf[namebuflen] = 0;          } -        return Host::SetThreadName (pid, tid, namebuf); +        return Host::SetThreadName (pid, tid, namebuf.get());      } - -    ::free(namebuf);      return false;  } @@ -1092,19 +1128,23 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)                      {                          framework_pos += strlen("LLDB.framework");                          ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path)); -                    } -#else -                    llvm::SmallString<256> python_version_dir; -                    llvm::raw_svector_ostream os(python_version_dir); -                    os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages"; -                    os.flush(); +                    }  +                    else  +                    { +#endif +                        llvm::SmallString<256> python_version_dir; +                        llvm::raw_svector_ostream os(python_version_dir); +                        os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages"; +                        os.flush(); -                    // We may get our string truncated. Should we protect -                    // this with an assert? +                        // We may get our string truncated. Should we protect +                        // this with an assert? -                    ::strncat(raw_path, python_version_dir.c_str(), -                              sizeof(raw_path) - strlen(raw_path) - 1); +                        ::strncat(raw_path, python_version_dir.c_str(), +                                  sizeof(raw_path) - strlen(raw_path) - 1); +#if defined (__APPLE__) +                    }  #endif                      FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));                      g_lldb_python_dir.SetCString(resolved_path); @@ -1224,6 +1264,29 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)              // TODO: where would user LLDB plug-ins be located on other systems?              return false;          } +             +    case ePathTypeLLDBTempSystemDir: +        { +            static ConstString g_lldb_tmp_dir; +            if (!g_lldb_tmp_dir) +            { +                const char *tmpdir_cstr = getenv("TMPDIR"); +                if (tmpdir_cstr == NULL) +                { +                    tmpdir_cstr = getenv("TMP"); +                    if (tmpdir_cstr == NULL) +                        tmpdir_cstr = getenv("TEMP"); +                } +                if (tmpdir_cstr) +                { +                    g_lldb_tmp_dir.SetCString(tmpdir_cstr); +                    if (log) +                        log->Printf("Host::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_lldb_tmp_dir.GetCString()); +                } +            } +            file_spec.GetDirectory() = g_lldb_tmp_dir; +            return (bool)file_spec.GetDirectory(); +        }      }      return false; @@ -1473,21 +1536,36 @@ Host::RunShellCommand (const char *command,      if (working_dir)          launch_info.SetWorkingDirectory(working_dir); -    char output_file_path_buffer[L_tmpnam]; +    char output_file_path_buffer[PATH_MAX];      const char *output_file_path = NULL; +          if (command_output_ptr)      {          // Create a temporary file to get the stdout/stderr and redirect the          // output of the command into this file. We will later read this file          // if all goes well and fill the data into "command_output_ptr" -        output_file_path = ::tmpnam(output_file_path_buffer); -        launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); +        FileSpec tmpdir_file_spec; +        if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) +        { +            tmpdir_file_spec.GetFilename().SetCString("lldb-shell-output.XXXXXX"); +            strncpy(output_file_path_buffer, tmpdir_file_spec.GetPath().c_str(), sizeof(output_file_path_buffer)); +        } +        else +        { +            strncpy(output_file_path_buffer, "/tmp/lldb-shell-output.XXXXXX", sizeof(output_file_path_buffer)); +        } +         +        output_file_path = ::mktemp(output_file_path_buffer); +    } +     +    launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); +    if (output_file_path) +    {          launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path, false, true);          launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);      }      else      { -        launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);          launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true);          launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true);      } @@ -1569,24 +1647,73 @@ Host::RunShellCommand (const char *command,      return error;  } -#if defined(__linux__) || defined(__FreeBSD__) -// The functions below implement process launching via posix_spawn() for Linux -// and FreeBSD. -// 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) +// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC +// systems + +#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) + +// this method needs to be visible to macosx/Host.cpp and +// common/Host.cpp. + +short +Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info) +{ +    short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + +#if defined (__APPLE__) +    if (launch_info.GetFlags().Test (eLaunchFlagExec)) +        flags |= POSIX_SPAWN_SETEXEC;           // Darwin specific posix_spawn flag +     +    if (launch_info.GetFlags().Test (eLaunchFlagDebug)) +        flags |= POSIX_SPAWN_START_SUSPENDED;   // Darwin specific posix_spawn flag +     +    if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) +        flags |= _POSIX_SPAWN_DISABLE_ASLR;     // Darwin specific posix_spawn flag +         +    if (launch_info.GetLaunchInSeparateProcessGroup()) +        flags |= POSIX_SPAWN_SETPGROUP; +     +#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT +#if defined (__APPLE__) && (defined (__x86_64__) || defined (__i386__)) +    static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; +    if (g_use_close_on_exec_flag == eLazyBoolCalculate) +    { +        g_use_close_on_exec_flag = eLazyBoolNo; +         +        uint32_t major, minor, update; +        if (Host::GetOSVersion(major, minor, update)) +        { +            // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or earlier +            if (major > 10 || (major == 10 && minor > 7)) +            { +                // Only enable for 10.8 and later OS versions +                g_use_close_on_exec_flag = eLazyBoolYes; +            } +        } +    } +#else +    static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; +#endif +    // Close all files exception those with file actions if this is supported. +    if (g_use_close_on_exec_flag == eLazyBoolYes) +        flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; +#endif +#endif // #if defined (__APPLE__) +    return flags; +} + +Error +Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)  {      Error error;      Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); -    assert(exe_path); -    assert(!launch_info.GetFlags().Test (eLaunchFlagDebug)); -      posix_spawnattr_t attr; -      error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); -    error.LogIfError(log, "::posix_spawnattr_init ( &attr )"); + +    if (error.Fail() || log) +        error.PutToLog(log, "::posix_spawnattr_init ( &attr )");      if (error.Fail())          return error; @@ -1598,52 +1725,82 @@ LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, :      sigset_t all_signals;      sigemptyset (&no_signals);      sigfillset (&all_signals); -    ::posix_spawnattr_setsigmask(&attr, &all_signals); +    ::posix_spawnattr_setsigmask(&attr, &no_signals); +#if defined (__linux__)  || defined (__FreeBSD__)      ::posix_spawnattr_setsigdefault(&attr, &no_signals); +#else +    ::posix_spawnattr_setsigdefault(&attr, &all_signals); +#endif -    short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; +    short flags = GetPosixspawnFlags(launch_info);      error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); -    error.LogIfError(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); +    if (error.Fail() || log) +        error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);      if (error.Fail())          return error; -    const size_t num_file_actions = launch_info.GetNumFileActions (); -    posix_spawn_file_actions_t file_actions, *file_action_ptr = NULL; -    // 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_action_ptr, NULL, posix_spawn_file_actions_destroy); +    // 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__) -    if (num_file_actions > 0) +    // 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(); +    cpu_type_t sub = arch_spec.GetMachOCPUSubType(); +    if (cpu != 0 && +        cpu != UINT32_MAX && +        cpu != LLDB_INVALID_CPUTYPE && +        !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail       { -        error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); -        error.LogIfError(log, "::posix_spawn_file_actions_init ( &file_actions )"); -        if (error.Fail()) +        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; +    } -        file_action_ptr = &file_actions; -        posix_spawn_file_actions_cleanup.set(file_action_ptr); +#endif -        for (size_t i = 0; i < num_file_actions; ++i) -        { -            const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); -            if (launch_file_action && -                !ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions, -                                                                         launch_file_action, -                                                                         log, -                                                                         error)) -                return error; -        } +    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;      } -    // Change working directory if neccessary. +#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 != NULL) +    if (working_dir)      { +#if defined (__APPLE__) +        // Set the working directory on this thread only +        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); @@ -1657,45 +1814,111 @@ LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, :              error.LogIfError(log, "unable to change working directory to %s", working_dir);              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(); - -    // Prepare minimal argument list if we didn't get it from the launch_info structure. -    // We must pass argv into posix_spawnp and it must contain at least two items - -    // pointer to an executable and NULL. -    if (argv == NULL) +    const size_t num_file_actions = launch_info.GetNumFileActions (); +    if (num_file_actions > 0)      { -        tmp_argv[0] = exe_path; -        tmp_argv[1] = NULL; -        argv = (char * const*)tmp_argv; -    } +        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, -                                    (num_file_actions > 0) ? &file_actions : NULL, -                                    &attr, -                                    argv, -                                    envp), -                    eErrorTypePOSIX); +        error.SetError (::posix_spawnp (&pid, +                                        exe_path, +                                        &file_actions, +                                        &attr, +                                        argv, +                                        envp), +                        eErrorTypePOSIX); -    error.LogIfError(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", -                     pid, exe_path, file_action_ptr, &attr, argv, envp); +        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]); +            } +        } -    // Change back the current directory. -    // NOTE: do not override previously established error from posix_spawnp. -    if (working_dir != NULL && ::chdir(current_dir) == -1 && error.Success()) +    } +    else      { -        error.SetError(errno, eErrorTypePOSIX); -        error.LogIfError(log, "unable to change current directory back to %s", -                         current_dir); +        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.  Error  Host::LaunchProcess (ProcessLaunchInfo &launch_info) @@ -1747,6 +1970,8 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)          // 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())          { @@ -1755,6 +1980,13 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)                                           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 | 
