Expand Up
@@ -73,10 +73,8 @@
#if defined(_WIN32)
#include " lldb/Host/windows/ProcessLauncherWindows.h"
#elif defined(__linux__) || defined(__NetBSD__)
#include " lldb/Host/posix/ProcessLauncherPosixFork.h"
#else
#include " lldb/Host/posix/ProcessLauncherPosix .h"
#include " lldb/Host/posix/ProcessLauncherPosixFork .h"
#endif
#if defined(__APPLE__)
Expand Down
Expand Up
@@ -602,359 +600,14 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
return error;
}
// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD, NetBSD and other GLIBC
// systems
#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || \
defined (__GLIBC__) || defined(__NetBSD__)
#if !defined(__ANDROID__)
// this method needs to be visible to macosx/Host.cpp and
// common/Host.cpp.
short Host::GetPosixspawnFlags (const 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 (HostInfo::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;
}
Status Host::LaunchProcessPosixSpawn (const char *exe_path,
const ProcessLaunchInfo &launch_info,
lldb::pid_t &pid) {
Status 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 ()) {
LLDB_LOG (log , " error: {0}, ::posix_spawnattr_init ( &attr )" , error);
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__) || defined(__FreeBSD__) || defined(__NetBSD__)
::posix_spawnattr_setsigdefault (&attr, &no_signals);
#else
::posix_spawnattr_setsigdefault (&attr, &all_signals);
#endif
short flags = GetPosixspawnFlags (launch_info);
error.SetError (::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
if (error.Fail ()) {
LLDB_LOG (log ,
" error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )" ,
error, flags);
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__)
// Don't set the binpref if a shell was provided. After all, that's only
// going to affect what version of the shell
// is launched, not what fork of the binary is launched. We insert "arch
// --arch <ARCH> as part of the shell invocation
// to do that job on OSX.
if (launch_info.GetShell () == nullptr ) {
// 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 != static_cast <cpu_type_t >(UINT32_MAX) &&
cpu != static_cast <cpu_type_t >(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 ())
LLDB_LOG (log , " error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "
" cpu_type = {1:x}, count => {2} )" ,
error, cpu, ocount);
if (error.Fail () || ocount != 1 )
return error;
}
}
#endif
const char *tmp_argv[2 ];
char *const *argv = const_cast <char *const *>(
launch_info.GetArguments ().GetConstArgumentVector ());
char *const *envp = const_cast <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 = const_cast <char *const *>(tmp_argv);
}
// The functions below implement process launching for non-Apple-based platforms
#if !defined(__APPLE__)
// manage the working directory
char current_dir[PATH_MAX];
current_dir[0 ] = ' \0 ' ;
#endif
FileSpec working_dir{launch_info.GetWorkingDirectory ()};
if (working_dir) {
#if defined(__APPLE__)
// Set the working directory on this thread only
if (__pthread_chdir (working_dir.GetCString ()) < 0 ) {
if (errno == ENOENT) {
error.SetErrorStringWithFormat (" No such file or directory: %s" ,
working_dir.GetCString ());
} else if (errno == ENOTDIR) {
error.SetErrorStringWithFormat (" Path doesn't name a directory: %s" ,
working_dir.GetCString ());
} 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);
LLDB_LOG (log , " error: {0}, unable to save the current directory" , error);
return error;
}
if (::chdir (working_dir.GetCString ()) == -1 ) {
error.SetError (errno, eErrorTypePOSIX);
LLDB_LOG (log , " error: {0}, unable to change working directory to {1}" ,
error, working_dir);
return error;
}
#endif
}
::pid_t result_pid = LLDB_INVALID_PROCESS_ID;
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 ()) {
LLDB_LOG (log ,
" error: {0}, ::posix_spawn_file_actions_init ( &file_actions )" ,
error);
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 FileAction *launch_file_action =
launch_info.GetFileActionAtIndex (i);
if (launch_file_action) {
if (!AddPosixSpawnFileAction (&file_actions, launch_file_action, log ,
error))
return error;
}
}
error.SetError (
::posix_spawnp (&result_pid, exe_path, &file_actions, &attr, argv, envp),
eErrorTypePOSIX);
if (error.Fail ()) {
LLDB_LOG (log , " error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', "
" file_actions = {3}, "
" attr = {4}, argv = {5}, envp = {6} )" ,
error, result_pid, exe_path, &file_actions, &attr, argv, envp);
if (log ) {
for (int ii = 0 ; argv[ii]; ++ii)
LLDB_LOG (log , " argv[{0}] = '{1}'" , ii, argv[ii]);
}
}
} else {
error.SetError (
::posix_spawnp (&result_pid, exe_path, NULL , &attr, argv, envp),
eErrorTypePOSIX);
if (error.Fail ()) {
LLDB_LOG (log , " error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', "
" file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )" ,
error, result_pid, exe_path, &attr, argv, envp);
if (log ) {
for (int ii = 0 ; argv[ii]; ++ii)
LLDB_LOG (log , " argv[{0}] = '{1}'" , ii, argv[ii]);
}
}
}
pid = result_pid;
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);
LLDB_LOG (log ,
" error: {0}, unable to change current directory back to {1}" ,
error, current_dir);
}
#endif
}
return error;
}
bool Host::AddPosixSpawnFileAction (void *_file_actions, const FileAction *info,
Log *log, Status &error) {
if (info == NULL )
return false ;
posix_spawn_file_actions_t *file_actions =
reinterpret_cast <posix_spawn_file_actions_t *>(_file_actions);
switch (info->GetAction ()) {
case FileAction::eFileActionNone:
error.Clear ();
break ;
case FileAction::eFileActionClose:
if (info->GetFD () == -1 )
error.SetErrorString (
" invalid fd for posix_spawn_file_actions_addclose(...)" );
else {
error.SetError (
::posix_spawn_file_actions_addclose (file_actions, info->GetFD ()),
eErrorTypePOSIX);
if (error.Fail())
LLDB_LOG(log, " error: {0}, posix_spawn_file_actions_addclose "
" (action={1}, fd={2})" ,
error, file_actions, info->GetFD ());
}
break ;
case FileAction::eFileActionDuplicate:
if (info->GetFD () == -1)
error.SetErrorString(
" invalid fd for posix_spawn_file_actions_adddup2(...)" );
else if (info->GetActionArgument () == -1)
error.SetErrorString(
" invalid duplicate fd for posix_spawn_file_actions_adddup2(...)" );
else {
error.SetError (
::posix_spawn_file_actions_adddup2 (file_actions, info->GetFD (),
info->GetActionArgument()),
eErrorTypePOSIX);
if (error.Fail())
LLDB_LOG(log, " error: {0}, posix_spawn_file_actions_adddup2 "
" (action={1}, fd={2}, dup_fd={3})" ,
error, file_actions, info->GetFD (), info->GetActionArgument());
}
break ;
case FileAction::eFileActionOpen:
if (info->GetFD () == -1)
error.SetErrorString(
" invalid fd in posix_spawn_file_actions_addopen(...)" );
else {
int oflag = info->GetActionArgument ();
mode_t mode = 0 ;
if (oflag & O_CREAT)
mode = 0640 ;
error.SetError (::posix_spawn_file_actions_addopen (
file_actions, info->GetFD (),
info->GetPath ().str ().c_str (), oflag, mode),
eErrorTypePOSIX);
if (error.Fail ())
LLDB_LOG (
log , " error: {0}, posix_spawn_file_actions_addopen (action={1}, "
" fd={2}, path='{3}', oflag={4}, mode={5})" ,
error, file_actions, info->GetFD (), info->GetPath (), oflag, mode);
}
break ;
}
return error.Success();
}
#endif // !defined(__ANDROID__)
#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) ||
// defined (__GLIBC__) || defined(__NetBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || \
defined (__NetBSD__) || defined(_WIN32)
// The functions below implement process launching via posix_spawn() for Linux,
// FreeBSD and NetBSD.
Status Host::LaunchProcess (ProcessLaunchInfo &launch_info) {
std::unique_ptr<ProcessLauncher> delegate_launcher;
#if defined(_WIN32)
delegate_launcher.reset (new ProcessLauncherWindows ());
#elif defined(__linux__) || defined(__NetBSD__)
delegate_launcher.reset (new ProcessLauncherPosixFork ());
#else
delegate_launcher.reset (new ProcessLauncherPosix ());
delegate_launcher.reset (new ProcessLauncherPosixFork ());
#endif
MonitoringProcessLauncher launcher (std::move (delegate_launcher));
Expand All
@@ -968,7 +621,7 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
return error;
}
#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__ )
#endif // ! defined(__APPLE__ )
#ifndef _WIN32
void Host::Kill (lldb::pid_t pid, int signo) { ::kill (pid, signo); }
Expand Down