1dda28197Spatrick //===-- Host.cpp ----------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick // C includes
10be691f3bSpatrick #include <cerrno>
11be691f3bSpatrick #include <climits>
12be691f3bSpatrick #include <cstdlib>
13061da546Spatrick #include <sys/types.h>
14061da546Spatrick #ifndef _WIN32
15061da546Spatrick #include <dlfcn.h>
16061da546Spatrick #include <grp.h>
17061da546Spatrick #include <netdb.h>
18061da546Spatrick #include <pwd.h>
19061da546Spatrick #include <sys/stat.h>
20061da546Spatrick #include <unistd.h>
21061da546Spatrick #endif
22061da546Spatrick
23061da546Spatrick #if defined(__APPLE__)
24061da546Spatrick #include <mach-o/dyld.h>
25061da546Spatrick #include <mach/mach_init.h>
26061da546Spatrick #include <mach/mach_port.h>
27061da546Spatrick #endif
28061da546Spatrick
29061da546Spatrick #if defined(__linux__) || defined(__FreeBSD__) || \
30061da546Spatrick defined(__FreeBSD_kernel__) || defined(__APPLE__) || \
31dda28197Spatrick defined(__NetBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
32061da546Spatrick #if !defined(__ANDROID__)
33061da546Spatrick #include <spawn.h>
34061da546Spatrick #endif
35061da546Spatrick #include <sys/syscall.h>
36061da546Spatrick #include <sys/wait.h>
37061da546Spatrick #endif
38061da546Spatrick
39061da546Spatrick #if defined(__FreeBSD__)
40061da546Spatrick #include <pthread_np.h>
41061da546Spatrick #endif
42061da546Spatrick
43061da546Spatrick #if defined(__NetBSD__)
44061da546Spatrick #include <lwp.h>
45061da546Spatrick #endif
46061da546Spatrick
47061da546Spatrick #include <csignal>
48061da546Spatrick
49061da546Spatrick #include "lldb/Host/FileAction.h"
50061da546Spatrick #include "lldb/Host/FileSystem.h"
51061da546Spatrick #include "lldb/Host/Host.h"
52061da546Spatrick #include "lldb/Host/HostInfo.h"
53061da546Spatrick #include "lldb/Host/HostProcess.h"
54061da546Spatrick #include "lldb/Host/MonitoringProcessLauncher.h"
55061da546Spatrick #include "lldb/Host/ProcessLaunchInfo.h"
56061da546Spatrick #include "lldb/Host/ProcessLauncher.h"
57061da546Spatrick #include "lldb/Host/ThreadLauncher.h"
58061da546Spatrick #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
59061da546Spatrick #include "lldb/Utility/FileSpec.h"
60*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
61061da546Spatrick #include "lldb/Utility/Log.h"
62061da546Spatrick #include "lldb/Utility/Predicate.h"
63061da546Spatrick #include "lldb/Utility/Status.h"
64061da546Spatrick #include "lldb/lldb-private-forward.h"
65061da546Spatrick #include "llvm/ADT/SmallString.h"
66061da546Spatrick #include "llvm/Support/Errno.h"
67061da546Spatrick #include "llvm/Support/FileSystem.h"
68061da546Spatrick
69061da546Spatrick #if defined(_WIN32)
70061da546Spatrick #include "lldb/Host/windows/ConnectionGenericFileWindows.h"
71061da546Spatrick #include "lldb/Host/windows/ProcessLauncherWindows.h"
72061da546Spatrick #else
73061da546Spatrick #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
74061da546Spatrick #endif
75061da546Spatrick
76061da546Spatrick #if defined(__APPLE__)
77061da546Spatrick #ifndef _POSIX_SPAWN_DISABLE_ASLR
78061da546Spatrick #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
79061da546Spatrick #endif
80061da546Spatrick
81061da546Spatrick extern "C" {
82061da546Spatrick int __pthread_chdir(const char *path);
83061da546Spatrick int __pthread_fchdir(int fildes);
84061da546Spatrick }
85061da546Spatrick
86061da546Spatrick #endif
87061da546Spatrick
88061da546Spatrick using namespace lldb;
89061da546Spatrick using namespace lldb_private;
90061da546Spatrick
91*f6aab3d8Srobert #if !defined(__APPLE__)
SystemLog(llvm::StringRef message)92*f6aab3d8Srobert void Host::SystemLog(llvm::StringRef message) { llvm::errs() << message; }
93*f6aab3d8Srobert #endif
94061da546Spatrick
95*f6aab3d8Srobert #if !defined(__APPLE__) && !defined(_WIN32)
96*f6aab3d8Srobert static thread_result_t
97*f6aab3d8Srobert MonitorChildProcessThreadFunction(::pid_t pid,
98*f6aab3d8Srobert Host::MonitorChildProcessCallback callback);
99061da546Spatrick
StartMonitoringChildProcess(const Host::MonitorChildProcessCallback & callback,lldb::pid_t pid)100061da546Spatrick llvm::Expected<HostThread> Host::StartMonitoringChildProcess(
101*f6aab3d8Srobert const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid) {
102061da546Spatrick char thread_name[256];
103061da546Spatrick ::snprintf(thread_name, sizeof(thread_name),
104061da546Spatrick "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
105*f6aab3d8Srobert assert(pid <= UINT32_MAX);
106*f6aab3d8Srobert return ThreadLauncher::LaunchThread(thread_name, [pid, callback] {
107*f6aab3d8Srobert return MonitorChildProcessThreadFunction(pid, callback);
108*f6aab3d8Srobert });
109061da546Spatrick }
110061da546Spatrick
111061da546Spatrick #ifndef __linux__
112061da546Spatrick // Scoped class that will disable thread canceling when it is constructed, and
113061da546Spatrick // exception safely restore the previous value it when it goes out of scope.
114061da546Spatrick class ScopedPThreadCancelDisabler {
115061da546Spatrick public:
ScopedPThreadCancelDisabler()116061da546Spatrick ScopedPThreadCancelDisabler() {
117061da546Spatrick // Disable the ability for this thread to be cancelled
118061da546Spatrick int err = ::pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m_old_state);
119061da546Spatrick if (err != 0)
120061da546Spatrick m_old_state = -1;
121061da546Spatrick }
122061da546Spatrick
~ScopedPThreadCancelDisabler()123061da546Spatrick ~ScopedPThreadCancelDisabler() {
124061da546Spatrick // Restore the ability for this thread to be cancelled to what it
125061da546Spatrick // previously was.
126061da546Spatrick if (m_old_state != -1)
127061da546Spatrick ::pthread_setcancelstate(m_old_state, 0);
128061da546Spatrick }
129061da546Spatrick
130061da546Spatrick private:
131061da546Spatrick int m_old_state; // Save the old cancelability state.
132061da546Spatrick };
133061da546Spatrick #endif // __linux__
134061da546Spatrick
135061da546Spatrick #ifdef __linux__
136061da546Spatrick #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
137061da546Spatrick static __thread volatile sig_atomic_t g_usr1_called;
138061da546Spatrick #else
139061da546Spatrick static thread_local volatile sig_atomic_t g_usr1_called;
140061da546Spatrick #endif
141061da546Spatrick
SigUsr1Handler(int)142061da546Spatrick static void SigUsr1Handler(int) { g_usr1_called = 1; }
143061da546Spatrick #endif // __linux__
144061da546Spatrick
CheckForMonitorCancellation()145061da546Spatrick static bool CheckForMonitorCancellation() {
146061da546Spatrick #ifdef __linux__
147061da546Spatrick if (g_usr1_called) {
148061da546Spatrick g_usr1_called = 0;
149061da546Spatrick return true;
150061da546Spatrick }
151061da546Spatrick #else
152061da546Spatrick ::pthread_testcancel();
153061da546Spatrick #endif
154061da546Spatrick return false;
155061da546Spatrick }
156061da546Spatrick
157*f6aab3d8Srobert static thread_result_t
MonitorChildProcessThreadFunction(::pid_t pid,Host::MonitorChildProcessCallback callback)158*f6aab3d8Srobert MonitorChildProcessThreadFunction(::pid_t pid,
159*f6aab3d8Srobert Host::MonitorChildProcessCallback callback) {
160*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Process);
161*f6aab3d8Srobert LLDB_LOG(log, "pid = {0}", pid);
162061da546Spatrick
163061da546Spatrick int status = -1;
164061da546Spatrick
165061da546Spatrick #ifdef __linux__
166061da546Spatrick // This signal is only used to interrupt the thread from waitpid
167061da546Spatrick struct sigaction sigUsr1Action;
168061da546Spatrick memset(&sigUsr1Action, 0, sizeof(sigUsr1Action));
169061da546Spatrick sigUsr1Action.sa_handler = SigUsr1Handler;
170061da546Spatrick ::sigaction(SIGUSR1, &sigUsr1Action, nullptr);
171061da546Spatrick #endif // __linux__
172061da546Spatrick
173*f6aab3d8Srobert while (true) {
174*f6aab3d8Srobert log = GetLog(LLDBLog::Process);
175*f6aab3d8Srobert LLDB_LOG(log, "::waitpid({0}, &status, 0)...", pid);
176061da546Spatrick
177061da546Spatrick if (CheckForMonitorCancellation())
178*f6aab3d8Srobert return nullptr;
179061da546Spatrick
180*f6aab3d8Srobert const ::pid_t wait_pid = ::waitpid(pid, &status, 0);
181*f6aab3d8Srobert
182*f6aab3d8Srobert LLDB_LOG(log, "::waitpid({0}, &status, 0) => pid = {1}, status = {2:x}", pid,
183*f6aab3d8Srobert wait_pid, status);
184061da546Spatrick
185061da546Spatrick if (CheckForMonitorCancellation())
186*f6aab3d8Srobert return nullptr;
187061da546Spatrick
188*f6aab3d8Srobert if (wait_pid != -1)
189061da546Spatrick break;
190*f6aab3d8Srobert if (errno != EINTR) {
191*f6aab3d8Srobert LLDB_LOG(log, "pid = {0}, thread exiting because waitpid failed ({1})...",
192*f6aab3d8Srobert pid, llvm::sys::StrError());
193*f6aab3d8Srobert return nullptr;
194061da546Spatrick }
195*f6aab3d8Srobert }
196*f6aab3d8Srobert
197061da546Spatrick int signal = 0;
198061da546Spatrick int exit_status = 0;
199*f6aab3d8Srobert if (WIFEXITED(status)) {
200061da546Spatrick exit_status = WEXITSTATUS(status);
201061da546Spatrick } else if (WIFSIGNALED(status)) {
202061da546Spatrick signal = WTERMSIG(status);
203061da546Spatrick exit_status = -1;
204061da546Spatrick } else {
205*f6aab3d8Srobert llvm_unreachable("Unknown status");
206061da546Spatrick }
207061da546Spatrick
208061da546Spatrick // Scope for pthread_cancel_disabler
209061da546Spatrick {
210061da546Spatrick #ifndef __linux__
211061da546Spatrick ScopedPThreadCancelDisabler pthread_cancel_disabler;
212061da546Spatrick #endif
213061da546Spatrick
214061da546Spatrick if (callback)
215*f6aab3d8Srobert callback(pid, signal, exit_status);
216061da546Spatrick }
217061da546Spatrick
218*f6aab3d8Srobert LLDB_LOG(GetLog(LLDBLog::Process), "pid = {0} thread exiting...", pid);
219061da546Spatrick return nullptr;
220061da546Spatrick }
221061da546Spatrick
222061da546Spatrick #endif // #if !defined (__APPLE__) && !defined (_WIN32)
223061da546Spatrick
GetCurrentProcessID()224061da546Spatrick lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); }
225061da546Spatrick
226061da546Spatrick #ifndef _WIN32
227061da546Spatrick
GetCurrentThread()228061da546Spatrick lldb::thread_t Host::GetCurrentThread() {
229061da546Spatrick return lldb::thread_t(pthread_self());
230061da546Spatrick }
231061da546Spatrick
GetSignalAsCString(int signo)232061da546Spatrick const char *Host::GetSignalAsCString(int signo) {
233061da546Spatrick switch (signo) {
234061da546Spatrick case SIGHUP:
235061da546Spatrick return "SIGHUP"; // 1 hangup
236061da546Spatrick case SIGINT:
237061da546Spatrick return "SIGINT"; // 2 interrupt
238061da546Spatrick case SIGQUIT:
239061da546Spatrick return "SIGQUIT"; // 3 quit
240061da546Spatrick case SIGILL:
241061da546Spatrick return "SIGILL"; // 4 illegal instruction (not reset when caught)
242061da546Spatrick case SIGTRAP:
243061da546Spatrick return "SIGTRAP"; // 5 trace trap (not reset when caught)
244061da546Spatrick case SIGABRT:
245061da546Spatrick return "SIGABRT"; // 6 abort()
246061da546Spatrick #if defined(SIGPOLL)
247061da546Spatrick #if !defined(SIGIO) || (SIGPOLL != SIGIO)
248061da546Spatrick // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to
249061da546Spatrick // fail with 'multiple define cases with same value'
250061da546Spatrick case SIGPOLL:
251061da546Spatrick return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
252061da546Spatrick #endif
253061da546Spatrick #endif
254061da546Spatrick #if defined(SIGEMT)
255061da546Spatrick case SIGEMT:
256061da546Spatrick return "SIGEMT"; // 7 EMT instruction
257061da546Spatrick #endif
258061da546Spatrick case SIGFPE:
259061da546Spatrick return "SIGFPE"; // 8 floating point exception
260061da546Spatrick case SIGKILL:
261061da546Spatrick return "SIGKILL"; // 9 kill (cannot be caught or ignored)
262061da546Spatrick case SIGBUS:
263061da546Spatrick return "SIGBUS"; // 10 bus error
264061da546Spatrick case SIGSEGV:
265061da546Spatrick return "SIGSEGV"; // 11 segmentation violation
266061da546Spatrick case SIGSYS:
267061da546Spatrick return "SIGSYS"; // 12 bad argument to system call
268061da546Spatrick case SIGPIPE:
269061da546Spatrick return "SIGPIPE"; // 13 write on a pipe with no one to read it
270061da546Spatrick case SIGALRM:
271061da546Spatrick return "SIGALRM"; // 14 alarm clock
272061da546Spatrick case SIGTERM:
273061da546Spatrick return "SIGTERM"; // 15 software termination signal from kill
274061da546Spatrick case SIGURG:
275061da546Spatrick return "SIGURG"; // 16 urgent condition on IO channel
276061da546Spatrick case SIGSTOP:
277061da546Spatrick return "SIGSTOP"; // 17 sendable stop signal not from tty
278061da546Spatrick case SIGTSTP:
279061da546Spatrick return "SIGTSTP"; // 18 stop signal from tty
280061da546Spatrick case SIGCONT:
281061da546Spatrick return "SIGCONT"; // 19 continue a stopped process
282061da546Spatrick case SIGCHLD:
283061da546Spatrick return "SIGCHLD"; // 20 to parent on child stop or exit
284061da546Spatrick case SIGTTIN:
285061da546Spatrick return "SIGTTIN"; // 21 to readers pgrp upon background tty read
286061da546Spatrick case SIGTTOU:
287061da546Spatrick return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP)
288061da546Spatrick #if defined(SIGIO)
289061da546Spatrick case SIGIO:
290061da546Spatrick return "SIGIO"; // 23 input/output possible signal
291061da546Spatrick #endif
292061da546Spatrick case SIGXCPU:
293061da546Spatrick return "SIGXCPU"; // 24 exceeded CPU time limit
294061da546Spatrick case SIGXFSZ:
295061da546Spatrick return "SIGXFSZ"; // 25 exceeded file size limit
296061da546Spatrick case SIGVTALRM:
297061da546Spatrick return "SIGVTALRM"; // 26 virtual time alarm
298061da546Spatrick case SIGPROF:
299061da546Spatrick return "SIGPROF"; // 27 profiling time alarm
300061da546Spatrick #if defined(SIGWINCH)
301061da546Spatrick case SIGWINCH:
302061da546Spatrick return "SIGWINCH"; // 28 window size changes
303061da546Spatrick #endif
304061da546Spatrick #if defined(SIGINFO)
305061da546Spatrick case SIGINFO:
306061da546Spatrick return "SIGINFO"; // 29 information request
307061da546Spatrick #endif
308061da546Spatrick case SIGUSR1:
309061da546Spatrick return "SIGUSR1"; // 30 user defined signal 1
310061da546Spatrick case SIGUSR2:
311061da546Spatrick return "SIGUSR2"; // 31 user defined signal 2
312061da546Spatrick default:
313061da546Spatrick break;
314061da546Spatrick }
315061da546Spatrick return nullptr;
316061da546Spatrick }
317061da546Spatrick
318061da546Spatrick #endif
319061da546Spatrick
320061da546Spatrick #if !defined(__APPLE__) // see Host.mm
321061da546Spatrick
GetBundleDirectory(const FileSpec & file,FileSpec & bundle)322061da546Spatrick bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) {
323061da546Spatrick bundle.Clear();
324061da546Spatrick return false;
325061da546Spatrick }
326061da546Spatrick
ResolveExecutableInBundle(FileSpec & file)327061da546Spatrick bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; }
328061da546Spatrick #endif
329061da546Spatrick
330061da546Spatrick #ifndef _WIN32
331061da546Spatrick
GetModuleFileSpecForHostAddress(const void * host_addr)332061da546Spatrick FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
333061da546Spatrick FileSpec module_filespec;
334061da546Spatrick #if !defined(__ANDROID__)
335061da546Spatrick Dl_info info;
336061da546Spatrick if (::dladdr(host_addr, &info)) {
337061da546Spatrick if (info.dli_fname) {
338061da546Spatrick module_filespec.SetFile(info.dli_fname, FileSpec::Style::native);
339061da546Spatrick FileSystem::Instance().Resolve(module_filespec);
340061da546Spatrick }
341061da546Spatrick }
342061da546Spatrick #endif
343061da546Spatrick return module_filespec;
344061da546Spatrick }
345061da546Spatrick
346061da546Spatrick #endif
347061da546Spatrick
348061da546Spatrick #if !defined(__linux__)
FindProcessThreads(const lldb::pid_t pid,TidMap & tids_to_attach)349061da546Spatrick bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) {
350061da546Spatrick return false;
351061da546Spatrick }
352061da546Spatrick #endif
353061da546Spatrick
354061da546Spatrick struct ShellInfo {
ShellInfoShellInfo355be691f3bSpatrick ShellInfo() : process_reaped(false) {}
356061da546Spatrick
357061da546Spatrick lldb_private::Predicate<bool> process_reaped;
358be691f3bSpatrick lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
359be691f3bSpatrick int signo = -1;
360be691f3bSpatrick int status = -1;
361061da546Spatrick };
362061da546Spatrick
363*f6aab3d8Srobert static void
MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info,lldb::pid_t pid,int signo,int status)364061da546Spatrick MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid,
365061da546Spatrick int signo, // Zero for no signal
366061da546Spatrick int status) // Exit value of process if signal is zero
367061da546Spatrick {
368061da546Spatrick shell_info->pid = pid;
369061da546Spatrick shell_info->signo = signo;
370061da546Spatrick shell_info->status = status;
371061da546Spatrick // Let the thread running Host::RunShellCommand() know that the process
372061da546Spatrick // exited and that ShellInfo has been filled in by broadcasting to it
373061da546Spatrick shell_info->process_reaped.SetValue(true, eBroadcastAlways);
374061da546Spatrick }
375061da546Spatrick
RunShellCommand(llvm::StringRef command,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output_ptr,const Timeout<std::micro> & timeout,bool run_in_shell,bool hide_stderr)376be691f3bSpatrick Status Host::RunShellCommand(llvm::StringRef command,
377be691f3bSpatrick const FileSpec &working_dir, int *status_ptr,
378be691f3bSpatrick int *signo_ptr, std::string *command_output_ptr,
379061da546Spatrick const Timeout<std::micro> &timeout,
380be691f3bSpatrick bool run_in_shell, bool hide_stderr) {
381be691f3bSpatrick return RunShellCommand(llvm::StringRef(), Args(command), working_dir,
382be691f3bSpatrick status_ptr, signo_ptr, command_output_ptr, timeout,
383be691f3bSpatrick run_in_shell, hide_stderr);
384be691f3bSpatrick }
385be691f3bSpatrick
RunShellCommand(llvm::StringRef shell_path,llvm::StringRef command,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output_ptr,const Timeout<std::micro> & timeout,bool run_in_shell,bool hide_stderr)386be691f3bSpatrick Status Host::RunShellCommand(llvm::StringRef shell_path,
387be691f3bSpatrick llvm::StringRef command,
388be691f3bSpatrick const FileSpec &working_dir, int *status_ptr,
389be691f3bSpatrick int *signo_ptr, std::string *command_output_ptr,
390be691f3bSpatrick const Timeout<std::micro> &timeout,
391be691f3bSpatrick bool run_in_shell, bool hide_stderr) {
392be691f3bSpatrick return RunShellCommand(shell_path, Args(command), working_dir, status_ptr,
393be691f3bSpatrick signo_ptr, command_output_ptr, timeout, run_in_shell,
394061da546Spatrick hide_stderr);
395061da546Spatrick }
396061da546Spatrick
RunShellCommand(const Args & args,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output_ptr,const Timeout<std::micro> & timeout,bool run_in_shell,bool hide_stderr)397061da546Spatrick Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
398061da546Spatrick int *status_ptr, int *signo_ptr,
399061da546Spatrick std::string *command_output_ptr,
400061da546Spatrick const Timeout<std::micro> &timeout,
401be691f3bSpatrick bool run_in_shell, bool hide_stderr) {
402be691f3bSpatrick return RunShellCommand(llvm::StringRef(), args, working_dir, status_ptr,
403be691f3bSpatrick signo_ptr, command_output_ptr, timeout, run_in_shell,
404be691f3bSpatrick hide_stderr);
405be691f3bSpatrick }
406be691f3bSpatrick
RunShellCommand(llvm::StringRef shell_path,const Args & args,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output_ptr,const Timeout<std::micro> & timeout,bool run_in_shell,bool hide_stderr)407be691f3bSpatrick Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
408be691f3bSpatrick const FileSpec &working_dir, int *status_ptr,
409be691f3bSpatrick int *signo_ptr, std::string *command_output_ptr,
410be691f3bSpatrick const Timeout<std::micro> &timeout,
411be691f3bSpatrick bool run_in_shell, bool hide_stderr) {
412061da546Spatrick Status error;
413061da546Spatrick ProcessLaunchInfo launch_info;
414061da546Spatrick launch_info.SetArchitecture(HostInfo::GetArchitecture());
415be691f3bSpatrick if (run_in_shell) {
416061da546Spatrick // Run the command in a shell
417be691f3bSpatrick FileSpec shell = HostInfo::GetDefaultShell();
418be691f3bSpatrick if (!shell_path.empty())
419be691f3bSpatrick shell.SetPath(shell_path);
420be691f3bSpatrick
421be691f3bSpatrick launch_info.SetShell(shell);
422061da546Spatrick launch_info.GetArguments().AppendArguments(args);
423061da546Spatrick const bool will_debug = false;
424061da546Spatrick const bool first_arg_is_full_shell_command = false;
425061da546Spatrick launch_info.ConvertArgumentsForLaunchingInShell(
426be691f3bSpatrick error, will_debug, first_arg_is_full_shell_command, 0);
427061da546Spatrick } else {
428061da546Spatrick // No shell, just run it
429061da546Spatrick const bool first_arg_is_executable = true;
430061da546Spatrick launch_info.SetArguments(args, first_arg_is_executable);
431061da546Spatrick }
432061da546Spatrick
433dda28197Spatrick launch_info.GetEnvironment() = Host::GetEnvironment();
434dda28197Spatrick
435061da546Spatrick if (working_dir)
436061da546Spatrick launch_info.SetWorkingDirectory(working_dir);
437061da546Spatrick llvm::SmallString<64> output_file_path;
438061da546Spatrick
439061da546Spatrick if (command_output_ptr) {
440061da546Spatrick // Create a temporary file to get the stdout/stderr and redirect the output
441061da546Spatrick // of the command into this file. We will later read this file if all goes
442061da546Spatrick // well and fill the data into "command_output_ptr"
443061da546Spatrick if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
444061da546Spatrick tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%");
445061da546Spatrick llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(),
446061da546Spatrick output_file_path);
447061da546Spatrick } else {
448061da546Spatrick llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "",
449061da546Spatrick output_file_path);
450061da546Spatrick }
451061da546Spatrick }
452061da546Spatrick
453dda28197Spatrick FileSpec output_file_spec(output_file_path.str());
454061da546Spatrick // Set up file descriptors.
455061da546Spatrick launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false);
456061da546Spatrick if (output_file_spec)
457061da546Spatrick launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false,
458061da546Spatrick true);
459061da546Spatrick else
460061da546Spatrick launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
461061da546Spatrick
462061da546Spatrick if (output_file_spec && !hide_stderr)
463061da546Spatrick launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
464061da546Spatrick else
465061da546Spatrick launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true);
466061da546Spatrick
467061da546Spatrick std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo());
468061da546Spatrick launch_info.SetMonitorProcessCallback(
469061da546Spatrick std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1,
470*f6aab3d8Srobert std::placeholders::_2, std::placeholders::_3));
471061da546Spatrick
472061da546Spatrick error = LaunchProcess(launch_info);
473061da546Spatrick const lldb::pid_t pid = launch_info.GetProcessID();
474061da546Spatrick
475061da546Spatrick if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
476061da546Spatrick error.SetErrorString("failed to get process ID");
477061da546Spatrick
478061da546Spatrick if (error.Success()) {
479061da546Spatrick if (!shell_info_sp->process_reaped.WaitForValueEqualTo(true, timeout)) {
480061da546Spatrick error.SetErrorString("timed out waiting for shell command to complete");
481061da546Spatrick
482061da546Spatrick // Kill the process since it didn't complete within the timeout specified
483061da546Spatrick Kill(pid, SIGKILL);
484061da546Spatrick // Wait for the monitor callback to get the message
485061da546Spatrick shell_info_sp->process_reaped.WaitForValueEqualTo(
486061da546Spatrick true, std::chrono::seconds(1));
487061da546Spatrick } else {
488061da546Spatrick if (status_ptr)
489061da546Spatrick *status_ptr = shell_info_sp->status;
490061da546Spatrick
491061da546Spatrick if (signo_ptr)
492061da546Spatrick *signo_ptr = shell_info_sp->signo;
493061da546Spatrick
494061da546Spatrick if (command_output_ptr) {
495061da546Spatrick command_output_ptr->clear();
496061da546Spatrick uint64_t file_size =
497061da546Spatrick FileSystem::Instance().GetByteSize(output_file_spec);
498061da546Spatrick if (file_size > 0) {
499061da546Spatrick if (file_size > command_output_ptr->max_size()) {
500061da546Spatrick error.SetErrorStringWithFormat(
501061da546Spatrick "shell command output is too large to fit into a std::string");
502061da546Spatrick } else {
503*f6aab3d8Srobert WritableDataBufferSP Buffer =
504*f6aab3d8Srobert FileSystem::Instance().CreateWritableDataBuffer(
505*f6aab3d8Srobert output_file_spec);
506061da546Spatrick if (error.Success())
507*f6aab3d8Srobert command_output_ptr->assign(
508*f6aab3d8Srobert reinterpret_cast<char *>(Buffer->GetBytes()),
509061da546Spatrick Buffer->GetByteSize());
510061da546Spatrick }
511061da546Spatrick }
512061da546Spatrick }
513061da546Spatrick }
514061da546Spatrick }
515061da546Spatrick
516061da546Spatrick llvm::sys::fs::remove(output_file_spec.GetPath());
517061da546Spatrick return error;
518061da546Spatrick }
519061da546Spatrick
520061da546Spatrick // The functions below implement process launching for non-Apple-based
521061da546Spatrick // platforms
522061da546Spatrick #if !defined(__APPLE__)
LaunchProcess(ProcessLaunchInfo & launch_info)523061da546Spatrick Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
524061da546Spatrick std::unique_ptr<ProcessLauncher> delegate_launcher;
525061da546Spatrick #if defined(_WIN32)
526061da546Spatrick delegate_launcher.reset(new ProcessLauncherWindows());
527061da546Spatrick #else
528061da546Spatrick delegate_launcher.reset(new ProcessLauncherPosixFork());
529061da546Spatrick #endif
530061da546Spatrick MonitoringProcessLauncher launcher(std::move(delegate_launcher));
531061da546Spatrick
532061da546Spatrick Status error;
533061da546Spatrick HostProcess process = launcher.LaunchProcess(launch_info, error);
534061da546Spatrick
535061da546Spatrick // TODO(zturner): It would be better if the entire HostProcess were returned
536061da546Spatrick // instead of writing it into this structure.
537061da546Spatrick launch_info.SetProcessID(process.GetProcessId());
538061da546Spatrick
539061da546Spatrick return error;
540061da546Spatrick }
541061da546Spatrick #endif // !defined(__APPLE__)
542061da546Spatrick
543061da546Spatrick #ifndef _WIN32
Kill(lldb::pid_t pid,int signo)544061da546Spatrick void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); }
545061da546Spatrick
546061da546Spatrick #endif
547061da546Spatrick
548061da546Spatrick #if !defined(__APPLE__)
OpenFileInExternalEditor(const FileSpec & file_spec,uint32_t line_no)549061da546Spatrick bool Host::OpenFileInExternalEditor(const FileSpec &file_spec,
550061da546Spatrick uint32_t line_no) {
551061da546Spatrick return false;
552061da546Spatrick }
553061da546Spatrick
IsInteractiveGraphicSession()554*f6aab3d8Srobert bool Host::IsInteractiveGraphicSession() { return false; }
555061da546Spatrick #endif
556061da546Spatrick
CreateDefaultConnection(llvm::StringRef url)557061da546Spatrick std::unique_ptr<Connection> Host::CreateDefaultConnection(llvm::StringRef url) {
558061da546Spatrick #if defined(_WIN32)
559061da546Spatrick if (url.startswith("file://"))
560061da546Spatrick return std::unique_ptr<Connection>(new ConnectionGenericFile());
561061da546Spatrick #endif
562061da546Spatrick return std::unique_ptr<Connection>(new ConnectionFileDescriptor());
563061da546Spatrick }
564061da546Spatrick
565061da546Spatrick #if defined(LLVM_ON_UNIX)
Decode(int wstatus)566061da546Spatrick WaitStatus WaitStatus::Decode(int wstatus) {
567061da546Spatrick if (WIFEXITED(wstatus))
568061da546Spatrick return {Exit, uint8_t(WEXITSTATUS(wstatus))};
569061da546Spatrick else if (WIFSIGNALED(wstatus))
570061da546Spatrick return {Signal, uint8_t(WTERMSIG(wstatus))};
571061da546Spatrick else if (WIFSTOPPED(wstatus))
572061da546Spatrick return {Stop, uint8_t(WSTOPSIG(wstatus))};
573061da546Spatrick llvm_unreachable("Unknown wait status");
574061da546Spatrick }
575061da546Spatrick #endif
576061da546Spatrick
format(const WaitStatus & WS,raw_ostream & OS,StringRef Options)577061da546Spatrick void llvm::format_provider<WaitStatus>::format(const WaitStatus &WS,
578061da546Spatrick raw_ostream &OS,
579061da546Spatrick StringRef Options) {
580061da546Spatrick if (Options == "g") {
581061da546Spatrick char type;
582061da546Spatrick switch (WS.type) {
583061da546Spatrick case WaitStatus::Exit:
584061da546Spatrick type = 'W';
585061da546Spatrick break;
586061da546Spatrick case WaitStatus::Signal:
587061da546Spatrick type = 'X';
588061da546Spatrick break;
589061da546Spatrick case WaitStatus::Stop:
590061da546Spatrick type = 'S';
591061da546Spatrick break;
592061da546Spatrick }
593061da546Spatrick OS << formatv("{0}{1:x-2}", type, WS.status);
594061da546Spatrick return;
595061da546Spatrick }
596061da546Spatrick
597061da546Spatrick assert(Options.empty());
598061da546Spatrick const char *desc;
599061da546Spatrick switch(WS.type) {
600061da546Spatrick case WaitStatus::Exit:
601061da546Spatrick desc = "Exited with status";
602061da546Spatrick break;
603061da546Spatrick case WaitStatus::Signal:
604061da546Spatrick desc = "Killed by signal";
605061da546Spatrick break;
606061da546Spatrick case WaitStatus::Stop:
607061da546Spatrick desc = "Stopped by signal";
608061da546Spatrick break;
609061da546Spatrick }
610061da546Spatrick OS << desc << " " << int(WS.status);
611061da546Spatrick }
612dda28197Spatrick
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)613dda28197Spatrick uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
614dda28197Spatrick ProcessInstanceInfoList &process_infos) {
615*f6aab3d8Srobert return FindProcessesImpl(match_info, process_infos);
616dda28197Spatrick }
617dda28197Spatrick
618*f6aab3d8Srobert char SystemLogHandler::ID;
619dda28197Spatrick
SystemLogHandler()620*f6aab3d8Srobert SystemLogHandler::SystemLogHandler() {}
621dda28197Spatrick
Emit(llvm::StringRef message)622*f6aab3d8Srobert void SystemLogHandler::Emit(llvm::StringRef message) {
623*f6aab3d8Srobert Host::SystemLog(message);
624dda28197Spatrick }
625