summaryrefslogtreecommitdiffstats
path: root/source/Host/common/Host.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Host/common/Host.cpp')
-rw-r--r--source/Host/common/Host.cpp180
1 files changed, 98 insertions, 82 deletions
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index 30f5c86..20d6355 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -64,6 +64,8 @@
#if defined(_WIN32)
#include "lldb/Host/windows/ProcessLauncherWindows.h"
+#elif defined(__ANDROID__) || defined(__ANDROID_NDK__)
+#include "lldb/Host/android/ProcessLauncherAndroid.h"
#else
#include "lldb/Host/posix/ProcessLauncherPosix.h"
#endif
@@ -111,7 +113,7 @@ Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, vo
return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL);
}
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
+#ifndef __linux__
//------------------------------------------------------------------
// Scoped class that will disable thread canceling when it is
// constructed, and exception safely restore the previous value it
@@ -138,7 +140,32 @@ public:
private:
int m_old_state; // Save the old cancelability state.
};
-#endif // __ANDROID_NDK__
+#endif // __linux__
+
+#ifdef __linux__
+static thread_local volatile sig_atomic_t g_usr1_called;
+
+static void
+SigUsr1Handler (int)
+{
+ g_usr1_called = 1;
+}
+#endif // __linux__
+
+static bool
+CheckForMonitorCancellation()
+{
+#ifdef __linux__
+ if (g_usr1_called)
+ {
+ g_usr1_called = 0;
+ return true;
+ }
+#else
+ ::pthread_testcancel ();
+#endif
+ return false;
+}
static thread_result_t
MonitorChildProcessThreadFunction (void *arg)
@@ -165,21 +192,29 @@ MonitorChildProcessThreadFunction (void *arg)
#endif
const int options = __WALL;
+#ifdef __linux__
+ // This signal is only used to interrupt the thread from waitpid
+ struct sigaction sigUsr1Action;
+ memset(&sigUsr1Action, 0, sizeof(sigUsr1Action));
+ sigUsr1Action.sa_handler = SigUsr1Handler;
+ ::sigaction(SIGUSR1, &sigUsr1Action, nullptr);
+#endif // __linux__
+
while (1)
{
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options);
- // Wait for all child processes
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
- ::pthread_testcancel ();
-#endif
+ if (CheckForMonitorCancellation ())
+ break;
+
// Get signals from all children with same process group of pid
const ::pid_t wait_pid = ::waitpid (pid, &status, options);
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
- ::pthread_testcancel ();
-#endif
+
+ if (CheckForMonitorCancellation ())
+ break;
+
if (wait_pid == -1)
{
if (errno == EINTR)
@@ -224,7 +259,7 @@ MonitorChildProcessThreadFunction (void *arg)
// Scope for pthread_cancel_disabler
{
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
+#ifndef __linux__
ScopedPThreadCancelDisabler pthread_cancel_disabler;
#endif
@@ -388,28 +423,6 @@ Host::GetSignalAsCString (int signo)
#endif
-void
-Host::WillTerminate ()
-{
-}
-
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) // see macosx/Host.mm
-
-void
-Host::Backtrace (Stream &strm, uint32_t max_frames)
-{
- // TODO: Is there a way to backtrace the current process on other systems?
-}
-
-size_t
-Host::GetEnvironment (StringList &env)
-{
- // TODO: Is there a way to the host environment for this process on other systems?
- return 0;
-}
-
-#endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__)
-
#ifndef _WIN32
lldb::thread_key_t
@@ -463,8 +476,6 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
if (info.dli_fname)
module_filespec.SetFile(info.dli_fname, true);
}
-#else
- assert(false && "dladdr() not supported on Android");
#endif
return module_filespec;
}
@@ -522,13 +533,25 @@ MonitorShellCommand (void *callback_baton,
}
Error
-Host::RunShellCommand (const char *command,
- const char *working_dir,
- int *status_ptr,
- int *signo_ptr,
- std::string *command_output_ptr,
- uint32_t timeout_sec,
- bool run_in_default_shell)
+Host::RunShellCommand(const char *command,
+ const FileSpec &working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output_ptr,
+ uint32_t timeout_sec,
+ bool run_in_default_shell)
+{
+ return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, command_output_ptr, timeout_sec, run_in_default_shell);
+}
+
+Error
+Host::RunShellCommand(const Args &args,
+ const FileSpec &working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output_ptr,
+ uint32_t timeout_sec,
+ bool run_in_default_shell)
{
Error error;
ProcessLaunchInfo launch_info;
@@ -537,10 +560,10 @@ Host::RunShellCommand (const char *command,
{
// Run the command in a shell
launch_info.SetShell(HostInfo::GetDefaultShell());
- launch_info.GetArguments().AppendArgument(command);
+ launch_info.GetArguments().AppendArguments(args);
const bool localhost = true;
const bool will_debug = false;
- const bool first_arg_is_full_shell_command = true;
+ const bool first_arg_is_full_shell_command = false;
launch_info.ConvertArgumentsForLaunchingInShell (error,
localhost,
will_debug,
@@ -550,7 +573,6 @@ Host::RunShellCommand (const char *command,
else
{
// No shell, just run it
- Args args (command);
const bool first_arg_is_executable = true;
launch_info.SetArguments(args, first_arg_is_executable);
}
@@ -558,7 +580,7 @@ Host::RunShellCommand (const char *command,
if (working_dir)
launch_info.SetWorkingDirectory(working_dir);
llvm::SmallString<PATH_MAX> output_file_path;
-
+
if (command_output_ptr)
{
// Create a temporary file to get the stdout/stderr and redirect the
@@ -575,11 +597,13 @@ Host::RunShellCommand (const char *command,
llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path);
}
}
-
+
+ FileSpec output_file_spec{output_file_path.c_str(), false};
+
launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
- if (!output_file_path.empty())
+ if (output_file_spec)
{
- launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path.c_str(), false, true);
+ launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, true);
launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
}
else
@@ -596,10 +620,10 @@ Host::RunShellCommand (const char *command,
error = LaunchProcess (launch_info);
const lldb::pid_t pid = launch_info.GetProcessID();
-
+
if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
error.SetErrorString("failed to get process ID");
-
+
if (error.Success())
{
// The process successfully launched, so we can defer ownership of
@@ -618,7 +642,7 @@ Host::RunShellCommand (const char *command,
if (timed_out)
{
error.SetErrorString("timed out waiting for shell command to complete");
-
+
// Kill the process since it didn't complete within the timeout specified
Kill (pid, SIGKILL);
// Wait for the monitor callback to get the message
@@ -631,15 +655,14 @@ Host::RunShellCommand (const char *command,
{
if (status_ptr)
*status_ptr = shell_info->status;
-
+
if (signo_ptr)
*signo_ptr = shell_info->signo;
-
+
if (command_output_ptr)
{
command_output_ptr->clear();
- FileSpec file_spec(output_file_path.c_str(), File::eOpenOptionRead);
- uint64_t file_size = file_spec.GetByteSize();
+ uint64_t file_size = output_file_spec.GetByteSize();
if (file_size > 0)
{
if (file_size > command_output_ptr->max_size())
@@ -648,8 +671,10 @@ Host::RunShellCommand (const char *command,
}
else
{
- command_output_ptr->resize(file_size);
- file_spec.ReadFileContents(0, &((*command_output_ptr)[0]), command_output_ptr->size(), &error);
+ std::vector<char> command_output(file_size);
+ output_file_spec.ReadFileContents(0, command_output.data(), file_size, &error);
+ if (error.Success())
+ command_output_ptr->assign(command_output.data(), file_size);
}
}
}
@@ -657,27 +682,25 @@ Host::RunShellCommand (const char *command,
shell_info->can_delete.SetValue(true, eBroadcastAlways);
}
- FileSpec output_file_spec(output_file_path.c_str(), false);
if (FileSystem::GetFileExists(output_file_spec))
- FileSystem::Unlink(output_file_path.c_str());
+ FileSystem::Unlink(output_file_spec);
// Handshake with the monitor thread, or just let it know in advance that
// it can delete "shell_info" in case we timed out and were not able to kill
// the process...
return error;
}
-
// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC
// systems
#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__)
+#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
// this method needs to be visible to macosx/Host.cpp and
// common/Host.cpp.
short
Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info)
{
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
#if defined (__APPLE__)
@@ -720,17 +743,12 @@ Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info)
#endif
#endif // #if defined (__APPLE__)
return flags;
-#else
- assert(false && "Host::GetPosixspawnFlags() not supported on Android");
- return 0;
-#endif
}
Error
Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
{
Error error;
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
posix_spawnattr_t attr;
@@ -816,16 +834,18 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
current_dir[0] = '\0';
#endif
- const char *working_dir = launch_info.GetWorkingDirectory();
+ 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) < 0) {
+ if (__pthread_chdir(working_dir.GetCString()) < 0) {
if (errno == ENOENT) {
- error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
+ 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);
+ 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.");
}
@@ -839,10 +859,11 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
return error;
}
- if (::chdir(working_dir) == -1)
+ if (::chdir(working_dir.GetCString()) == -1)
{
error.SetError(errno, eErrorTypePOSIX);
- error.LogIfError(log, "unable to change working directory to %s", working_dir);
+ error.LogIfError(log, "unable to change working directory to %s",
+ working_dir.GetCString());
return error;
}
#endif
@@ -920,9 +941,6 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
}
#endif
}
-#else
- error.SetErrorString("Host::LaunchProcessPosixSpawn() not supported on Android");
-#endif
return error;
}
@@ -930,7 +948,6 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
bool
Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error)
{
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
if (info == NULL)
return false;
@@ -993,12 +1010,9 @@ Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *
break;
}
return error.Success();
-#else
- error.SetErrorString("Host::AddPosixSpawnFileAction() not supported on Android");
- return false;
-#endif
}
-#endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems
+#endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
+#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,
@@ -1010,6 +1024,8 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
std::unique_ptr<ProcessLauncher> delegate_launcher;
#if defined(_WIN32)
delegate_launcher.reset(new ProcessLauncherWindows());
+#elif defined(__ANDROID__) || defined(__ANDROID_NDK__)
+ delegate_launcher.reset(new ProcessLauncherAndroid());
#else
delegate_launcher.reset(new ProcessLauncherPosix());
#endif
@@ -1054,7 +1070,7 @@ Host::SetCrashDescription (const char *description)
#endif
-#if !defined (__linux__) && !defined (__FreeBSD__) && !defined (__NetBSD__)
+#if !defined (__linux__) && !defined (__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined (__NetBSD__)
const lldb_private::UnixSignalsSP&
Host::GetUnixSignals ()
OpenPOWER on IntegriCloud