Bug Summary

File:tools/lldb/source/Host/common/Host.cpp
Warning:line 280, column 15
Use of memory after it is freed

Annotated Source Code

1//===-- Host.cpp ------------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C includes
11#include <errno(*__errno_location ()).h>
12#include <limits.h>
13#include <stdlib.h>
14#include <sys/types.h>
15#ifndef _WIN32
16#include <dlfcn.h>
17#include <grp.h>
18#include <netdb.h>
19#include <pwd.h>
20#include <sys/stat.h>
21#include <unistd.h>
22#endif
23
24#if defined(__APPLE__)
25#include <mach-o/dyld.h>
26#include <mach/mach_init.h>
27#include <mach/mach_port.h>
28#endif
29
30#if defined(__linux__1) || defined(__FreeBSD__) || \
31 defined(__FreeBSD_kernel__) || defined(__APPLE__) || \
32 defined(__NetBSD__) || defined(__OpenBSD__)
33#if !defined(__ANDROID__)
34#include <spawn.h>
35#endif
36#include <sys/syscall.h>
37#include <sys/wait.h>
38#endif
39
40#if defined(__FreeBSD__)
41#include <pthread_np.h>
42#endif
43
44#if defined(__NetBSD__)
45#include <lwp.h>
46#endif
47
48// C++ Includes
49
50// Other libraries and framework includes
51// Project includes
52
53#include "lldb/Core/ArchSpec.h"
54#include "lldb/Host/Host.h"
55#include "lldb/Host/HostInfo.h"
56#include "lldb/Host/HostProcess.h"
57#include "lldb/Host/MonitoringProcessLauncher.h"
58#include "lldb/Host/Predicate.h"
59#include "lldb/Host/ProcessLauncher.h"
60#include "lldb/Host/ThreadLauncher.h"
61#include "lldb/Target/FileAction.h"
62#include "lldb/Target/ProcessLaunchInfo.h"
63#include "lldb/Target/UnixSignals.h"
64#include "lldb/Utility/CleanUp.h"
65#include "lldb/Utility/DataBufferLLVM.h"
66#include "lldb/Utility/FileSpec.h"
67#include "lldb/Utility/Log.h"
68#include "lldb/Utility/Status.h"
69#include "lldb/lldb-private-forward.h"
70#include "llvm/ADT/SmallString.h"
71#include "llvm/Support/FileSystem.h"
72
73#if defined(_WIN32)
74#include "lldb/Host/windows/ProcessLauncherWindows.h"
75#elif defined(__linux__1) || defined(__NetBSD__)
76#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
77#else
78#include "lldb/Host/posix/ProcessLauncherPosix.h"
79#endif
80
81#if defined(__APPLE__)
82#ifndef _POSIX_SPAWN_DISABLE_ASLR
83#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
84#endif
85
86extern "C" {
87int __pthread_chdir(const char *path);
88int __pthread_fchdir(int fildes);
89}
90
91#endif
92
93using namespace lldb;
94using namespace lldb_private;
95
96#if !defined(__APPLE__) && !defined(_WIN32)
97struct MonitorInfo {
98 lldb::pid_t pid; // The process ID to monitor
99 Host::MonitorChildProcessCallback
100 callback; // The callback function to call when "pid" exits or signals
101 bool monitor_signals; // If true, call the callback when "pid" gets signaled.
102};
103
104static thread_result_t MonitorChildProcessThreadFunction(void *arg);
105
106HostThread Host::StartMonitoringChildProcess(
107 const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid,
108 bool monitor_signals) {
109 MonitorInfo *info_ptr = new MonitorInfo();
110
111 info_ptr->pid = pid;
112 info_ptr->callback = callback;
113 info_ptr->monitor_signals = monitor_signals;
114
115 char thread_name[256];
116 ::snprintf(thread_name, sizeof(thread_name),
117 "<lldb.host.wait4(pid=%" PRIu64"l" "u" ")>", pid);
118 return ThreadLauncher::LaunchThread(
119 thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL__null);
120}
121
122#ifndef __linux__1
123//------------------------------------------------------------------
124// Scoped class that will disable thread canceling when it is
125// constructed, and exception safely restore the previous value it
126// when it goes out of scope.
127//------------------------------------------------------------------
128class ScopedPThreadCancelDisabler {
129public:
130 ScopedPThreadCancelDisabler() {
131 // Disable the ability for this thread to be cancelled
132 int err = ::pthread_setcancelstate(PTHREAD_CANCEL_DISABLEPTHREAD_CANCEL_DISABLE, &m_old_state);
133 if (err != 0)
134 m_old_state = -1;
135 }
136
137 ~ScopedPThreadCancelDisabler() {
138 // Restore the ability for this thread to be cancelled to what it
139 // previously was.
140 if (m_old_state != -1)
141 ::pthread_setcancelstate(m_old_state, 0);
142 }
143
144private:
145 int m_old_state; // Save the old cancelability state.
146};
147#endif // __linux__
148
149#ifdef __linux__1
150#if defined(__GNUC__4) && (__GNUC__4 < 4 || (__GNUC__4 == 4 && __GNUC_MINOR__2 < 8))
151static __thread volatile sig_atomic_t g_usr1_called;
152#else
153static thread_local volatile sig_atomic_t g_usr1_called;
154#endif
155
156static void SigUsr1Handler(int) { g_usr1_called = 1; }
157#endif // __linux__
158
159static bool CheckForMonitorCancellation() {
160#ifdef __linux__1
161 if (g_usr1_called) {
162 g_usr1_called = 0;
163 return true;
164 }
165#else
166 ::pthread_testcancel();
167#endif
168 return false;
169}
170
171static thread_result_t MonitorChildProcessThreadFunction(void *arg) {
172 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1)));
173 const char *function = __FUNCTION__;
174 if (log)
1
Assuming 'log' is null
2
Taking false branch
175 log->Printf("%s (arg = %p) thread starting...", function, arg);
176
177 MonitorInfo *info = (MonitorInfo *)arg;
178
179 const Host::MonitorChildProcessCallback callback = info->callback;
180 const bool monitor_signals = info->monitor_signals;
181
182 assert(info->pid <= UINT32_MAX)((info->pid <= (4294967295U)) ? static_cast<void>
(0) : __assert_fail ("info->pid <= UINT32_MAX", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, 182, __PRETTY_FUNCTION__))
;
183 const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid;
3
Assuming 'monitor_signals' is 0
4
'?' condition is false
184
185 delete info;
5
Memory is released
186
187 int status = -1;
188#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
189#define __WALL0x40000000 0
190#endif
191 const int options = __WALL0x40000000;
192
193#ifdef __linux__1
194 // This signal is only used to interrupt the thread from waitpid
195 struct sigaction sigUsr1Action;
196 memset(&sigUsr1Action, 0, sizeof(sigUsr1Action));
197 sigUsr1Action.sa_handler__sigaction_handler.sa_handler = SigUsr1Handler;
198 ::sigaction(SIGUSR110, &sigUsr1Action, nullptr);
199#endif // __linux__
200
201 while (1) {
6
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
202 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1));
203 if (log)
7
Assuming 'log' is null
8
Taking false branch
16
Assuming 'log' is null
17
Taking false branch
204 log->Printf("%s ::waitpid (pid = %" PRIi32"i" ", &status, options = %i)...",
205 function, pid, options);
206
207 if (CheckForMonitorCancellation())
9
Taking false branch
18
Taking false branch
208 break;
209
210 // Get signals from all children with same process group of pid
211 const ::pid_t wait_pid = ::waitpid(pid, &status, options);
212
213 if (CheckForMonitorCancellation())
10
Taking false branch
19
Taking false branch
214 break;
215
216 if (wait_pid == -1) {
11
Assuming the condition is false
12
Taking false branch
20
Assuming the condition is false
21
Taking false branch
217 if (errno(*__errno_location ()) == EINTR4)
218 continue;
219 else {
220 if (log)
221 log->Printf(
222 "%s (arg = %p) thread exiting because waitpid failed (%s)...",
223 __FUNCTION__, arg, strerror(errno(*__errno_location ())));
224 break;
225 }
226 } else if (wait_pid > 0) {
13
Assuming 'wait_pid' is <= 0
14
Taking false branch
22
Assuming 'wait_pid' is > 0
23
Taking true branch
227 bool exited = false;
228 int signal = 0;
229 int exit_status = 0;
230 const char *status_cstr = NULL__null;
231 if (WIFSTOPPED(status)(((status) & 0xff) == 0x7f)) {
24
Taking false branch
232 signal = WSTOPSIG(status)(((status) & 0xff00) >> 8);
233 status_cstr = "STOPPED";
234 } else if (WIFEXITED(status)(((status) & 0x7f) == 0)) {
25
Taking true branch
235 exit_status = WEXITSTATUS(status)(((status) & 0xff00) >> 8);
236 status_cstr = "EXITED";
237 exited = true;
238 } else if (WIFSIGNALED(status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0
)
) {
239 signal = WTERMSIG(status)((status) & 0x7f);
240 status_cstr = "SIGNALED";
241 if (wait_pid == abs(pid)) {
242 exited = true;
243 exit_status = -1;
244 }
245 } else {
246 status_cstr = "(\?\?\?)";
247 }
248
249 // Scope for pthread_cancel_disabler
250 {
251#ifndef __linux__1
252 ScopedPThreadCancelDisabler pthread_cancel_disabler;
253#endif
254
255 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1));
256 if (log)
26
Assuming 'log' is non-null
27
Taking true branch
257 log->Printf("%s ::waitpid (pid = %" PRIi32"i"
258 ", &status, options = %i) => pid = %" PRIi32"i"
259 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
260 function, pid, options, wait_pid, status, status_cstr,
261 signal, exit_status);
262
263 if (exited || (signal != 0 && monitor_signals)) {
264 bool callback_return = false;
265 if (callback)
28
Taking true branch
266 callback_return = callback(wait_pid, exited, signal, exit_status);
267
268 // If our process exited, then this thread should exit
269 if (exited && wait_pid == abs(pid)) {
29
Taking false branch
270 if (log)
271 log->Printf("%s (arg = %p) thread exiting because pid received "
272 "exit signal...",
273 __FUNCTION__, arg);
274 break;
275 }
276 // If the callback returns true, it means this process should
277 // exit
278 if (callback_return) {
30
Assuming 'callback_return' is not equal to 0
31
Taking true branch
279 if (log)
32
Taking true branch
280 log->Printf("%s (arg = %p) thread exiting because callback "
33
Use of memory after it is freed
281 "returned true...",
282 __FUNCTION__, arg);
283 break;
284 }
285 }
286 }
287 }
288 }
289
290 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1));
291 if (log)
292 log->Printf("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
293
294 return NULL__null;
295}
296
297#endif // #if !defined (__APPLE__) && !defined (_WIN32)
298
299#if !defined(__APPLE__)
300
301void Host::SystemLog(SystemLogType type, const char *format, va_list args) {
302 vfprintf(stderrstderr, format, args);
303}
304
305#endif
306
307void Host::SystemLog(SystemLogType type, const char *format, ...) {
308 va_list args;
309 va_start(args, format)__builtin_va_start(args, format);
310 SystemLog(type, format, args);
311 va_end(args)__builtin_va_end(args);
312}
313
314lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); }
315
316#ifndef _WIN32
317
318lldb::thread_t Host::GetCurrentThread() {
319 return lldb::thread_t(pthread_self());
320}
321
322const char *Host::GetSignalAsCString(int signo) {
323 switch (signo) {
324 case SIGHUP1:
325 return "SIGHUP"; // 1 hangup
326 case SIGINT2:
327 return "SIGINT"; // 2 interrupt
328 case SIGQUIT3:
329 return "SIGQUIT"; // 3 quit
330 case SIGILL4:
331 return "SIGILL"; // 4 illegal instruction (not reset when caught)
332 case SIGTRAP5:
333 return "SIGTRAP"; // 5 trace trap (not reset when caught)
334 case SIGABRT6:
335 return "SIGABRT"; // 6 abort()
336#if defined(SIGPOLL29)
337#if !defined(SIGIO29) || (SIGPOLL29 != SIGIO29)
338 // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to
339 // fail with 'multiple define cases with same value'
340 case SIGPOLL29:
341 return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
342#endif
343#endif
344#if defined(SIGEMT)
345 case SIGEMT:
346 return "SIGEMT"; // 7 EMT instruction
347#endif
348 case SIGFPE8:
349 return "SIGFPE"; // 8 floating point exception
350 case SIGKILL9:
351 return "SIGKILL"; // 9 kill (cannot be caught or ignored)
352 case SIGBUS7:
353 return "SIGBUS"; // 10 bus error
354 case SIGSEGV11:
355 return "SIGSEGV"; // 11 segmentation violation
356 case SIGSYS31:
357 return "SIGSYS"; // 12 bad argument to system call
358 case SIGPIPE13:
359 return "SIGPIPE"; // 13 write on a pipe with no one to read it
360 case SIGALRM14:
361 return "SIGALRM"; // 14 alarm clock
362 case SIGTERM15:
363 return "SIGTERM"; // 15 software termination signal from kill
364 case SIGURG23:
365 return "SIGURG"; // 16 urgent condition on IO channel
366 case SIGSTOP19:
367 return "SIGSTOP"; // 17 sendable stop signal not from tty
368 case SIGTSTP20:
369 return "SIGTSTP"; // 18 stop signal from tty
370 case SIGCONT18:
371 return "SIGCONT"; // 19 continue a stopped process
372 case SIGCHLD17:
373 return "SIGCHLD"; // 20 to parent on child stop or exit
374 case SIGTTIN21:
375 return "SIGTTIN"; // 21 to readers pgrp upon background tty read
376 case SIGTTOU22:
377 return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local&LTOSTOP)
378#if defined(SIGIO29)
379 case SIGIO29:
380 return "SIGIO"; // 23 input/output possible signal
381#endif
382 case SIGXCPU24:
383 return "SIGXCPU"; // 24 exceeded CPU time limit
384 case SIGXFSZ25:
385 return "SIGXFSZ"; // 25 exceeded file size limit
386 case SIGVTALRM26:
387 return "SIGVTALRM"; // 26 virtual time alarm
388 case SIGPROF27:
389 return "SIGPROF"; // 27 profiling time alarm
390#if defined(SIGWINCH28)
391 case SIGWINCH28:
392 return "SIGWINCH"; // 28 window size changes
393#endif
394#if defined(SIGINFO)
395 case SIGINFO:
396 return "SIGINFO"; // 29 information request
397#endif
398 case SIGUSR110:
399 return "SIGUSR1"; // 30 user defined signal 1
400 case SIGUSR212:
401 return "SIGUSR2"; // 31 user defined signal 2
402 default:
403 break;
404 }
405 return NULL__null;
406}
407
408#endif
409
410#ifndef _WIN32
411
412lldb::thread_key_t
413Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) {
414 pthread_key_t key;
415 ::pthread_key_create(&key, callback);
416 return key;
417}
418
419void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) {
420 return ::pthread_getspecific(key);
421}
422
423void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) {
424 ::pthread_setspecific(key, value);
425}
426
427#endif
428
429#if !defined(__APPLE__) // see Host.mm
430
431bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) {
432 bundle.Clear();
433 return false;
434}
435
436bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; }
437#endif
438
439#ifndef _WIN32
440
441FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
442 FileSpec module_filespec;
443#if !defined(__ANDROID__)
444 Dl_info info;
445 if (::dladdr(host_addr, &info)) {
446 if (info.dli_fname)
447 module_filespec.SetFile(info.dli_fname, true);
448 }
449#endif
450 return module_filespec;
451}
452
453#endif
454
455#if !defined(__linux__1)
456bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) {
457 return false;
458}
459#endif
460
461struct ShellInfo {
462 ShellInfo()
463 : process_reaped(false), pid(LLDB_INVALID_PROCESS_ID0), signo(-1),
464 status(-1) {}
465
466 lldb_private::Predicate<bool> process_reaped;
467 lldb::pid_t pid;
468 int signo;
469 int status;
470};
471
472static bool
473MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid,
474 bool exited, // True if the process did exit
475 int signo, // Zero for no signal
476 int status) // Exit value of process if signal is zero
477{
478 shell_info->pid = pid;
479 shell_info->signo = signo;
480 shell_info->status = status;
481 // Let the thread running Host::RunShellCommand() know that the process
482 // exited and that ShellInfo has been filled in by broadcasting to it
483 shell_info->process_reaped.SetValue(true, eBroadcastAlways);
484 return true;
485}
486
487Status Host::RunShellCommand(const char *command, const FileSpec &working_dir,
488 int *status_ptr, int *signo_ptr,
489 std::string *command_output_ptr,
490 uint32_t timeout_sec, bool run_in_default_shell) {
491 return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr,
492 command_output_ptr, timeout_sec, run_in_default_shell);
493}
494
495Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
496 int *status_ptr, int *signo_ptr,
497 std::string *command_output_ptr,
498 uint32_t timeout_sec, bool run_in_default_shell) {
499 Status error;
500 ProcessLaunchInfo launch_info;
501 launch_info.SetArchitecture(HostInfo::GetArchitecture());
502 if (run_in_default_shell) {
503 // Run the command in a shell
504 launch_info.SetShell(HostInfo::GetDefaultShell());
505 launch_info.GetArguments().AppendArguments(args);
506 const bool localhost = true;
507 const bool will_debug = false;
508 const bool first_arg_is_full_shell_command = false;
509 launch_info.ConvertArgumentsForLaunchingInShell(
510 error, localhost, will_debug, first_arg_is_full_shell_command, 0);
511 } else {
512 // No shell, just run it
513 const bool first_arg_is_executable = true;
514 launch_info.SetArguments(args, first_arg_is_executable);
515 }
516
517 if (working_dir)
518 launch_info.SetWorkingDirectory(working_dir);
519 llvm::SmallString<PATH_MAX4096> output_file_path;
520
521 if (command_output_ptr) {
522 // Create a temporary file to get the stdout/stderr and redirect the
523 // output of the command into this file. We will later read this file
524 // if all goes well and fill the data into "command_output_ptr"
525 FileSpec tmpdir_file_spec;
526 if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) {
527 tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%");
528 llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(),
529 output_file_path);
530 } else {
531 llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "",
532 output_file_path);
533 }
534 }
535
536 FileSpec output_file_spec{output_file_path.c_str(), false};
537
538 launch_info.AppendSuppressFileAction(STDIN_FILENO0, true, false);
539 if (output_file_spec) {
540 launch_info.AppendOpenFileAction(STDOUT_FILENO1, output_file_spec, false,
541 true);
542 launch_info.AppendDuplicateFileAction(STDOUT_FILENO1, STDERR_FILENO2);
543 } else {
544 launch_info.AppendSuppressFileAction(STDOUT_FILENO1, false, true);
545 launch_info.AppendSuppressFileAction(STDERR_FILENO2, false, true);
546 }
547
548 std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo());
549 const bool monitor_signals = false;
550 launch_info.SetMonitorProcessCallback(
551 std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1,
552 std::placeholders::_2, std::placeholders::_3,
553 std::placeholders::_4),
554 monitor_signals);
555
556 error = LaunchProcess(launch_info);
557 const lldb::pid_t pid = launch_info.GetProcessID();
558
559 if (error.Success() && pid == LLDB_INVALID_PROCESS_ID0)
560 error.SetErrorString("failed to get process ID");
561
562 if (error.Success()) {
563 bool timed_out = false;
564 shell_info_sp->process_reaped.WaitForValueEqualTo(
565 true, std::chrono::seconds(timeout_sec), &timed_out);
566 if (timed_out) {
567 error.SetErrorString("timed out waiting for shell command to complete");
568
569 // Kill the process since it didn't complete within the timeout specified
570 Kill(pid, SIGKILL9);
571 // Wait for the monitor callback to get the message
572 timed_out = false;
573 shell_info_sp->process_reaped.WaitForValueEqualTo(
574 true, std::chrono::seconds(1), &timed_out);
575 } else {
576 if (status_ptr)
577 *status_ptr = shell_info_sp->status;
578
579 if (signo_ptr)
580 *signo_ptr = shell_info_sp->signo;
581
582 if (command_output_ptr) {
583 command_output_ptr->clear();
584 uint64_t file_size = output_file_spec.GetByteSize();
585 if (file_size > 0) {
586 if (file_size > command_output_ptr->max_size()) {
587 error.SetErrorStringWithFormat(
588 "shell command output is too large to fit into a std::string");
589 } else {
590 auto Buffer =
591 DataBufferLLVM::CreateFromPath(output_file_spec.GetPath());
592 if (error.Success())
593 command_output_ptr->assign(Buffer->GetChars(),
594 Buffer->GetByteSize());
595 }
596 }
597 }
598 }
599 }
600
601 llvm::sys::fs::remove(output_file_spec.GetPath());
602 return error;
603}
604
605// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD, NetBSD and other GLIBC
606// systems
607
608#if defined(__APPLE__) || defined(__linux__1) || defined(__FreeBSD__) || \
609 defined(__GLIBC__2) || defined(__NetBSD__)
610#if !defined(__ANDROID__)
611// this method needs to be visible to macosx/Host.cpp and
612// common/Host.cpp.
613
614short Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) {
615 short flags = POSIX_SPAWN_SETSIGDEF0x04 | POSIX_SPAWN_SETSIGMASK0x08;
616
617#if defined(__APPLE__)
618 if (launch_info.GetFlags().Test(eLaunchFlagExec))
619 flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag
620
621 if (launch_info.GetFlags().Test(eLaunchFlagDebug))
622 flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag
623
624 if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
625 flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag
626
627 if (launch_info.GetLaunchInSeparateProcessGroup())
628 flags |= POSIX_SPAWN_SETPGROUP0x02;
629
630#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
631#if defined(__APPLE__) && (defined(__x86_64__1) || defined(__i386__))
632 static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate;
633 if (g_use_close_on_exec_flag == eLazyBoolCalculate) {
634 g_use_close_on_exec_flag = eLazyBoolNo;
635
636 uint32_t major, minor, update;
637 if (HostInfo::GetOSVersion(major, minor, update)) {
638 // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or
639 // earlier
640 if (major > 10 || (major == 10 && minor > 7)) {
641 // Only enable for 10.8 and later OS versions
642 g_use_close_on_exec_flag = eLazyBoolYes;
643 }
644 }
645 }
646#else
647 static LazyBool g_use_close_on_exec_flag = eLazyBoolYes;
648#endif
649 // Close all files exception those with file actions if this is supported.
650 if (g_use_close_on_exec_flag == eLazyBoolYes)
651 flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
652#endif
653#endif // #if defined (__APPLE__)
654 return flags;
655}
656
657Status Host::LaunchProcessPosixSpawn(const char *exe_path,
658 const ProcessLaunchInfo &launch_info,
659 lldb::pid_t &pid) {
660 Status error;
661 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST(1u << 14) |
662 LIBLLDB_LOG_PROCESS(1u << 1)));
663
664 posix_spawnattr_t attr;
665 error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX);
666
667 if (error.Fail()) {
668 LLDB_LOG(log, "error: {0}, ::posix_spawnattr_init ( &attr )", error)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_init ( &attr )"
, error); } while (0)
;
669 return error;
670 }
671
672 // Make a quick class that will cleanup the posix spawn attributes in case
673 // we return in the middle of this function.
674 lldb_utility::CleanUp<posix_spawnattr_t *, int> posix_spawnattr_cleanup(
675 &attr, posix_spawnattr_destroy);
676
677 sigset_t no_signals;
678 sigset_t all_signals;
679 sigemptyset(&no_signals);
680 sigfillset(&all_signals);
681 ::posix_spawnattr_setsigmask(&attr, &no_signals);
682#if defined(__linux__1) || defined(__FreeBSD__) || defined(__NetBSD__)
683 ::posix_spawnattr_setsigdefault(&attr, &no_signals);
684#else
685 ::posix_spawnattr_setsigdefault(&attr, &all_signals);
686#endif
687
688 short flags = GetPosixspawnFlags(launch_info);
689
690 error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX);
691 if (error.Fail()) {
692 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )"
, error, flags); } while (0)
693 "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )"
, error, flags); } while (0)
694 error, flags)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )"
, error, flags); } while (0)
;
695 return error;
696 }
697
698// posix_spawnattr_setbinpref_np appears to be an Apple extension per:
699// http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/
700#if defined(__APPLE__) && !defined(__arm__)
701
702 // Don't set the binpref if a shell was provided. After all, that's only
703 // going to affect what version of the shell
704 // is launched, not what fork of the binary is launched. We insert "arch
705 // --arch <ARCH> as part of the shell invocation
706 // to do that job on OSX.
707
708 if (launch_info.GetShell() == nullptr) {
709 // We don't need to do this for ARM, and we really shouldn't now that we
710 // have multiple CPU subtypes and no posix_spawnattr call that allows us
711 // to set which CPU subtype to launch...
712 const ArchSpec &arch_spec = launch_info.GetArchitecture();
713 cpu_type_t cpu = arch_spec.GetMachOCPUType();
714 cpu_type_t sub = arch_spec.GetMachOCPUSubType();
715 if (cpu != 0 && cpu != static_cast<cpu_type_t>(UINT32_MAX(4294967295U)) &&
716 cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE(0xFFFFFFFEu)) &&
717 !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try
718 // to set the CPU type or we will fail
719 {
720 size_t ocount = 0;
721 error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount),
722 eErrorTypePOSIX);
723 if (error.Fail())
724 LLDB_LOG(log, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "
"cpu_type = {1:x}, count => {2} )", error, cpu, ocount); }
while (0)
725 "cpu_type = {1:x}, count => {2} )",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "
"cpu_type = {1:x}, count => {2} )", error, cpu, ocount); }
while (0)
726 error, cpu, ocount)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "
"cpu_type = {1:x}, count => {2} )", error, cpu, ocount); }
while (0)
;
727
728 if (error.Fail() || ocount != 1)
729 return error;
730 }
731 }
732
733#endif
734
735 const char *tmp_argv[2];
736 char *const *argv = const_cast<char *const *>(
737 launch_info.GetArguments().GetConstArgumentVector());
738 char *const *envp = const_cast<char *const *>(
739 launch_info.GetEnvironmentEntries().GetConstArgumentVector());
740 if (argv == NULL__null) {
741 // posix_spawn gets very unhappy if it doesn't have at least the program
742 // name in argv[0]. One of the side affects I have noticed is the
743 // environment
744 // variables don't make it into the child process if "argv == NULL"!!!
745 tmp_argv[0] = exe_path;
746 tmp_argv[1] = NULL__null;
747 argv = const_cast<char *const *>(tmp_argv);
748 }
749
750#if !defined(__APPLE__)
751 // manage the working directory
752 char current_dir[PATH_MAX4096];
753 current_dir[0] = '\0';
754#endif
755
756 FileSpec working_dir{launch_info.GetWorkingDirectory()};
757 if (working_dir) {
758#if defined(__APPLE__)
759 // Set the working directory on this thread only
760 if (__pthread_chdir(working_dir.GetCString()) < 0) {
761 if (errno(*__errno_location ()) == ENOENT2) {
762 error.SetErrorStringWithFormat("No such file or directory: %s",
763 working_dir.GetCString());
764 } else if (errno(*__errno_location ()) == ENOTDIR20) {
765 error.SetErrorStringWithFormat("Path doesn't name a directory: %s",
766 working_dir.GetCString());
767 } else {
768 error.SetErrorStringWithFormat("An unknown error occurred when "
769 "changing directory for process "
770 "execution.");
771 }
772 return error;
773 }
774#else
775 if (::getcwd(current_dir, sizeof(current_dir)) == NULL__null) {
776 error.SetError(errno(*__errno_location ()), eErrorTypePOSIX);
777 LLDB_LOG(log, "error: {0}, unable to save the current directory", error)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to save the current directory"
, error); } while (0)
;
778 return error;
779 }
780
781 if (::chdir(working_dir.GetCString()) == -1) {
782 error.SetError(errno(*__errno_location ()), eErrorTypePOSIX);
783 LLDB_LOG(log, "error: {0}, unable to change working directory to {1}",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change working directory to {1}"
, error, working_dir); } while (0)
784 error, working_dir)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change working directory to {1}"
, error, working_dir); } while (0)
;
785 return error;
786 }
787#endif
788 }
789
790 ::pid_t result_pid = LLDB_INVALID_PROCESS_ID0;
791 const size_t num_file_actions = launch_info.GetNumFileActions();
792 if (num_file_actions > 0) {
793 posix_spawn_file_actions_t file_actions;
794 error.SetError(::posix_spawn_file_actions_init(&file_actions),
795 eErrorTypePOSIX);
796 if (error.Fail()) {
797 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )"
, error); } while (0)
798 "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )"
, error); } while (0)
799 error)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )"
, error); } while (0)
;
800 return error;
801 }
802
803 // Make a quick class that will cleanup the posix spawn attributes in case
804 // we return in the middle of this function.
805 lldb_utility::CleanUp<posix_spawn_file_actions_t *, int>
806 posix_spawn_file_actions_cleanup(&file_actions,
807 posix_spawn_file_actions_destroy);
808
809 for (size_t i = 0; i < num_file_actions; ++i) {
810 const FileAction *launch_file_action =
811 launch_info.GetFileActionAtIndex(i);
812 if (launch_file_action) {
813 if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log,
814 error))
815 return error;
816 }
817 }
818
819 error.SetError(
820 ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp),
821 eErrorTypePOSIX);
822
823 if (error.Fail()) {
824 LLDB_LOG(log, "error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while (0)
825 "file_actions = {3}, "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while (0)
826 "attr = {4}, argv = {5}, envp = {6} )",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while (0)
827 error, result_pid, exe_path, &file_actions, &attr, argv, envp)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while (0)
;
828 if (log) {
829 for (int ii = 0; argv[ii]; ++ii)
830 LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii])do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "argv[{0}] = '{1}'", ii, argv[ii]); } while (
0)
;
831 }
832 }
833
834 } else {
835 error.SetError(
836 ::posix_spawnp(&result_pid, exe_path, NULL__null, &attr, argv, envp),
837 eErrorTypePOSIX);
838
839 if (error.Fail()) {
840 LLDB_LOG(log, "error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
841 "file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
842 error, result_pid, exe_path, &attr, argv, envp)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
;
843 if (log) {
844 for (int ii = 0; argv[ii]; ++ii)
845 LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii])do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "argv[{0}] = '{1}'", ii, argv[ii]); } while (
0)
;
846 }
847 }
848 }
849 pid = result_pid;
850
851 if (working_dir) {
852#if defined(__APPLE__)
853 // No more thread specific current working directory
854 __pthread_fchdir(-1);
855#else
856 if (::chdir(current_dir) == -1 && error.Success()) {
857 error.SetError(errno(*__errno_location ()), eErrorTypePOSIX);
858 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change current directory back to {1}"
, error, current_dir); } while (0)
859 "error: {0}, unable to change current directory back to {1}",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change current directory back to {1}"
, error, current_dir); } while (0)
860 error, current_dir)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change current directory back to {1}"
, error, current_dir); } while (0)
;
861 }
862#endif
863 }
864
865 return error;
866}
867
868bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info,
869 Log *log, Status &error) {
870 if (info == NULL__null)
871 return false;
872
873 posix_spawn_file_actions_t *file_actions =
874 reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions);
875
876 switch (info->GetAction()) {
877 case FileAction::eFileActionNone:
878 error.Clear();
879 break;
880
881 case FileAction::eFileActionClose:
882 if (info->GetFD() == -1)
883 error.SetErrorString(
884 "invalid fd for posix_spawn_file_actions_addclose(...)");
885 else {
886 error.SetError(
887 ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()),
888 eErrorTypePOSIX);
889 if (error.Fail())
890 LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_addclose "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, posix_spawn_file_actions_addclose "
"(action={1}, fd={2})", error, file_actions, info->GetFD(
)); } while (0)
891 "(action={1}, fd={2})",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, posix_spawn_file_actions_addclose "
"(action={1}, fd={2})", error, file_actions, info->GetFD(
)); } while (0)
892 error, file_actions, info->GetFD())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, posix_spawn_file_actions_addclose "
"(action={1}, fd={2})", error, file_actions, info->GetFD(
)); } while (0)
;
893 }
894 break;
895
896 case FileAction::eFileActionDuplicate:
897 if (info->GetFD() == -1)
898 error.SetErrorString(
899 "invalid fd for posix_spawn_file_actions_adddup2(...)");
900 else if (info->GetActionArgument() == -1)
901 error.SetErrorString(
902 "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
903 else {
904 error.SetError(
905 ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(),
906 info->GetActionArgument()),
907 eErrorTypePOSIX);
908 if (error.Fail())
909 LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_adddup2 "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, posix_spawn_file_actions_adddup2 "
"(action={1}, fd={2}, dup_fd={3})", error, file_actions, info
->GetFD(), info->GetActionArgument()); } while (0)
910 "(action={1}, fd={2}, dup_fd={3})",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, posix_spawn_file_actions_adddup2 "
"(action={1}, fd={2}, dup_fd={3})", error, file_actions, info
->GetFD(), info->GetActionArgument()); } while (0)
911 error, file_actions, info->GetFD(), info->GetActionArgument())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, posix_spawn_file_actions_adddup2 "
"(action={1}, fd={2}, dup_fd={3})", error, file_actions, info
->GetFD(), info->GetActionArgument()); } while (0)
;
912 }
913 break;
914
915 case FileAction::eFileActionOpen:
916 if (info->GetFD() == -1)
917 error.SetErrorString(
918 "invalid fd in posix_spawn_file_actions_addopen(...)");
919 else {
920 int oflag = info->GetActionArgument();
921
922 mode_t mode = 0;
923
924 if (oflag & O_CREAT0100)
925 mode = 0640;
926
927 error.SetError(::posix_spawn_file_actions_addopen(
928 file_actions, info->GetFD(),
929 info->GetPath().str().c_str(), oflag, mode),
930 eErrorTypePOSIX);
931 if (error.Fail())
932 LLDB_LOG(do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
933 log, "error: {0}, posix_spawn_file_actions_addopen (action={1}, "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
934 "fd={2}, path='{3}', oflag={4}, mode={5})",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
935 error, file_actions, info->GetFD(), info->GetPath(), oflag, mode)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303373/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "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); } while
(0)
;
936 }
937 break;
938 }
939 return error.Success();
940}
941#endif // !defined(__ANDROID__)
942#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) ||
943 // defined (__GLIBC__) || defined(__NetBSD__)
944
945#if defined(__linux__1) || defined(__FreeBSD__) || defined(__GLIBC__2) || \
946 defined(__NetBSD__) || defined(_WIN32)
947// The functions below implement process launching via posix_spawn() for Linux,
948// FreeBSD and NetBSD.
949
950Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
951 std::unique_ptr<ProcessLauncher> delegate_launcher;
952#if defined(_WIN32)
953 delegate_launcher.reset(new ProcessLauncherWindows());
954#elif defined(__linux__1) || defined(__NetBSD__)
955 delegate_launcher.reset(new ProcessLauncherPosixFork());
956#else
957 delegate_launcher.reset(new ProcessLauncherPosix());
958#endif
959 MonitoringProcessLauncher launcher(std::move(delegate_launcher));
960
961 Status error;
962 HostProcess process = launcher.LaunchProcess(launch_info, error);
963
964 // TODO(zturner): It would be better if the entire HostProcess were returned
965 // instead of writing
966 // it into this structure.
967 launch_info.SetProcessID(process.GetProcessId());
968
969 return error;
970}
971#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
972
973#ifndef _WIN32
974void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); }
975
976#endif
977
978#if !defined(__APPLE__)
979bool Host::OpenFileInExternalEditor(const FileSpec &file_spec,
980 uint32_t line_no) {
981 return false;
982}
983
984#endif
985
986const UnixSignalsSP &Host::GetUnixSignals() {
987 static const auto s_unix_signals_sp =
988 UnixSignals::Create(HostInfo::GetArchitecture());
989 return s_unix_signals_sp;
990}