[Lldb-commits] [lldb] r199856 - Unify OS X/POSIX/Linux Host spawn support.
Todd Fiala
tfiala at google.com
Wed Jan 22 16:52:29 PST 2014
Author: tfiala
Date: Wed Jan 22 18:52:28 2014
New Revision: 199856
URL: http://llvm.org/viewvc/llvm-project?rev=199856&view=rev
Log:
Unify OS X/POSIX/Linux Host spawn support.
This fixes a bug under Linux where spawning a process via
Host::LaunchProcess was disabling all blockable signals on the
launched process. This caused strange behavior when attempting
to kill the lldb-gdbserver process, as the child generally would
not die unless killed with a non-blockable signal (e.g. 'kill -9').
This change moves several functions out of macosx/Host.mm into
common/Host.cpp. In addition, two functions that needed to work
across common/Host.cpp and macosx/Host.mm were moved into the Host.h
header file.
Modified:
lldb/trunk/include/lldb/Host/Host.h
lldb/trunk/source/Host/common/Host.cpp
lldb/trunk/source/Host/macosx/Host.mm
Modified: lldb/trunk/include/lldb/Host/Host.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Host.h?rev=199856&r1=199855&r2=199856&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/Host.h (original)
+++ lldb/trunk/include/lldb/Host/Host.h Wed Jan 22 18:52:28 2014
@@ -476,7 +476,15 @@ public:
static bool
GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
-
+
+#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__)
+ static short
+ GetPosixspawnFlags (ProcessLaunchInfo &launch_info);
+
+ static Error
+ LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid);
+#endif
+
static lldb::pid_t
LaunchApplication (const FileSpec &app_file_spec);
Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=199856&r1=199855&r2=199856&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Wed Jan 22 18:52:28 2014
@@ -38,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>
@@ -69,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;
@@ -1637,24 +1649,73 @@ Host::RunShellCommand (const char *comma
return error;
}
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__)
-// 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;
@@ -1666,52 +1727,82 @@ LaunchProcessPosixSpawn (const char *exe
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__)
::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__)
+
+ // 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
+ {
+ 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 (num_file_actions > 0)
- {
- error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
- error.LogIfError(log, "::posix_spawn_file_actions_init ( &file_actions )");
- if (error.Fail())
+ 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);
@@ -1725,45 +1816,111 @@ LaunchProcessPosixSpawn (const char *exe
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();
+ 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;
- // 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)
+ // 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
{
- tmp_argv[0] = exe_path;
- tmp_argv[1] = NULL;
- argv = (char * const*)tmp_argv;
+ 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]);
+ }
+ }
}
- error.SetError (::posix_spawnp (&pid,
- exe_path,
- (num_file_actions > 0) ? &file_actions : NULL,
- &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);
-
- // 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())
- {
- error.SetError(errno, eErrorTypePOSIX);
- error.LogIfError(log, "unable to change current directory back to %s",
- current_dir);
+ 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)
@@ -1815,6 +1972,8 @@ Host::LaunchProcess (ProcessLaunchInfo &
// 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,6 +1982,13 @@ Host::LaunchProcess (ProcessLaunchInfo &
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
Modified: lldb/trunk/source/Host/macosx/Host.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Host.mm?rev=199856&r1=199855&r2=199856&view=diff
==============================================================================
--- lldb/trunk/source/Host/macosx/Host.mm (original)
+++ lldb/trunk/source/Host/macosx/Host.mm Wed Jan 22 18:52:28 2014
@@ -1318,51 +1318,6 @@ Host::GetProcessInfo (lldb::pid_t pid, P
return false;
}
-static short
-GetPosixspawnFlags (ProcessLaunchInfo &launch_info)
-{
- short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
- 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
-
- return flags;
-}
-
#if !NO_XPC_SERVICES
static void
PackageXPCArguments (xpc_object_t message, const char *prefix, const Args& args)
@@ -1543,7 +1498,7 @@ LaunchProcessXPC (const char *exe_path,
// Posix spawn stuff.
xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, launch_info.GetArchitecture().GetMachOCPUType());
- xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, GetPosixspawnFlags(launch_info));
+ xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, Host::GetPosixspawnFlags(launch_info));
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, message);
xpc_type_t returnType = xpc_get_type(reply);
@@ -1586,178 +1541,6 @@ LaunchProcessXPC (const char *exe_path,
#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();
- 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
- {
- 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-commits
mailing list