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__) || defined(__NetBSD__)
32#if !defined(__ANDROID__)
33#include <spawn.h>
34#endif
35#include <sys/syscall.h>
36#include <sys/wait.h>
37#endif
38
39#if defined(__FreeBSD__)
40#include <pthread_np.h>
41#endif
42
43#if defined(__NetBSD__)
44#include <lwp.h>
45#endif
46
47// C++ Includes
48
49// Other libraries and framework includes
50// Project includes
51
52#include "lldb/Core/ArchSpec.h"
53#include "lldb/Host/FileSpec.h"
54#include "lldb/Host/FileSystem.h"
55#include "lldb/Host/Host.h"
56#include "lldb/Host/HostInfo.h"
57#include "lldb/Host/HostProcess.h"
58#include "lldb/Host/MonitoringProcessLauncher.h"
59#include "lldb/Host/Predicate.h"
60#include "lldb/Host/ProcessLauncher.h"
61#include "lldb/Host/ThreadLauncher.h"
62#include "lldb/Target/FileAction.h"
63#include "lldb/Target/ProcessLaunchInfo.h"
64#include "lldb/Target/UnixSignals.h"
65#include "lldb/Utility/CleanUp.h"
66#include "lldb/Utility/DataBufferLLVM.h"
67#include "lldb/Utility/Error.h"
68#include "lldb/Utility/Log.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~svn298304/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__)
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
487Error 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
495Error 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 Error 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 if (FileSystem::GetFileExists(output_file_spec))
602 FileSystem::Unlink(output_file_spec);
603 return error;
604}
605
606// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD, NetBSD and other GLIBC
607// systems
608
609#if defined(__APPLE__) || defined(__linux__1) || defined(__FreeBSD__) || \
610 defined(__GLIBC__2) || defined(__NetBSD__)
611#if !defined(__ANDROID__)
612// this method needs to be visible to macosx/Host.cpp and
613// common/Host.cpp.
614
615short Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) {
616 short flags = POSIX_SPAWN_SETSIGDEF0x04 | POSIX_SPAWN_SETSIGMASK0x08;
617
618#if defined(__APPLE__)
619 if (launch_info.GetFlags().Test(eLaunchFlagExec))
620 flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag
621
622 if (launch_info.GetFlags().Test(eLaunchFlagDebug))
623 flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag
624
625 if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
626 flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag
627
628 if (launch_info.GetLaunchInSeparateProcessGroup())
629 flags |= POSIX_SPAWN_SETPGROUP0x02;
630
631#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
632#if defined(__APPLE__) && (defined(__x86_64__1) || defined(__i386__))
633 static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate;
634 if (g_use_close_on_exec_flag == eLazyBoolCalculate) {
635 g_use_close_on_exec_flag = eLazyBoolNo;
636
637 uint32_t major, minor, update;
638 if (HostInfo::GetOSVersion(major, minor, update)) {
639 // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or
640 // earlier
641 if (major > 10 || (major == 10 && minor > 7)) {
642 // Only enable for 10.8 and later OS versions
643 g_use_close_on_exec_flag = eLazyBoolYes;
644 }
645 }
646 }
647#else
648 static LazyBool g_use_close_on_exec_flag = eLazyBoolYes;
649#endif
650 // Close all files exception those with file actions if this is supported.
651 if (g_use_close_on_exec_flag == eLazyBoolYes)
652 flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
653#endif
654#endif // #if defined (__APPLE__)
655 return flags;
656}
657
658Error Host::LaunchProcessPosixSpawn(const char *exe_path,
659 const ProcessLaunchInfo &launch_info,
660 lldb::pid_t &pid) {
661 Error error;
662 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST(1u << 14) |
663 LIBLLDB_LOG_PROCESS(1u << 1)));
664
665 posix_spawnattr_t attr;
666 error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX);
667
668 if (error.Fail()) {
669 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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_init ( &attr )"
, error); } while (0)
;
670 return error;
671 }
672
673 // Make a quick class that will cleanup the posix spawn attributes in case
674 // we return in the middle of this function.
675 lldb_utility::CleanUp<posix_spawnattr_t *, int> posix_spawnattr_cleanup(
676 &attr, posix_spawnattr_destroy);
677
678 sigset_t no_signals;
679 sigset_t all_signals;
680 sigemptyset(&no_signals);
681 sigfillset(&all_signals);
682 ::posix_spawnattr_setsigmask(&attr, &no_signals);
683#if defined(__linux__1) || defined(__FreeBSD__)
684 ::posix_spawnattr_setsigdefault(&attr, &no_signals);
685#else
686 ::posix_spawnattr_setsigdefault(&attr, &all_signals);
687#endif
688
689 short flags = GetPosixspawnFlags(launch_info);
690
691 error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX);
692 if (error.Fail()) {
693 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )"
, error, flags); } while (0)
694 "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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )"
, error, flags); } while (0)
695 error, flags)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )"
, error, flags); } while (0)
;
696 return error;
697 }
698
699// posix_spawnattr_setbinpref_np appears to be an Apple extension per:
700// http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/
701#if defined(__APPLE__) && !defined(__arm__)
702
703 // Don't set the binpref if a shell was provided. After all, that's only
704 // going to affect what version of the shell
705 // is launched, not what fork of the binary is launched. We insert "arch
706 // --arch <ARCH> as part of the shell invocation
707 // to do that job on OSX.
708
709 if (launch_info.GetShell() == nullptr) {
710 // We don't need to do this for ARM, and we really shouldn't now that we
711 // have multiple CPU subtypes and no posix_spawnattr call that allows us
712 // to set which CPU subtype to launch...
713 const ArchSpec &arch_spec = launch_info.GetArchitecture();
714 cpu_type_t cpu = arch_spec.GetMachOCPUType();
715 cpu_type_t sub = arch_spec.GetMachOCPUSubType();
716 if (cpu != 0 && cpu != static_cast<cpu_type_t>(UINT32_MAX(4294967295U)) &&
717 cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE(0xFFFFFFFEu)) &&
718 !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try
719 // to set the CPU type or we will fail
720 {
721 size_t ocount = 0;
722 error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount),
723 eErrorTypePOSIX);
724 if (error.Fail())
725 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~svn298304/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 "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~svn298304/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 error, cpu, ocount)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/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)
;
728
729 if (error.Fail() || ocount != 1)
730 return error;
731 }
732 }
733
734#endif
735
736 const char *tmp_argv[2];
737 char *const *argv = const_cast<char *const *>(
738 launch_info.GetArguments().GetConstArgumentVector());
739 char *const *envp = const_cast<char *const *>(
740 launch_info.GetEnvironmentEntries().GetConstArgumentVector());
741 if (argv == NULL__null) {
742 // posix_spawn gets very unhappy if it doesn't have at least the program
743 // name in argv[0]. One of the side affects I have noticed is the
744 // environment
745 // variables don't make it into the child process if "argv == NULL"!!!
746 tmp_argv[0] = exe_path;
747 tmp_argv[1] = NULL__null;
748 argv = const_cast<char *const *>(tmp_argv);
749 }
750
751#if !defined(__APPLE__)
752 // manage the working directory
753 char current_dir[PATH_MAX4096];
754 current_dir[0] = '\0';
755#endif
756
757 FileSpec working_dir{launch_info.GetWorkingDirectory()};
758 if (working_dir) {
759#if defined(__APPLE__)
760 // Set the working directory on this thread only
761 if (__pthread_chdir(working_dir.GetCString()) < 0) {
762 if (errno(*__errno_location ()) == ENOENT2) {
763 error.SetErrorStringWithFormat("No such file or directory: %s",
764 working_dir.GetCString());
765 } else if (errno(*__errno_location ()) == ENOTDIR20) {
766 error.SetErrorStringWithFormat("Path doesn't name a directory: %s",
767 working_dir.GetCString());
768 } else {
769 error.SetErrorStringWithFormat("An unknown error occurred when "
770 "changing directory for process "
771 "execution.");
772 }
773 return error;
774 }
775#else
776 if (::getcwd(current_dir, sizeof(current_dir)) == NULL__null) {
777 error.SetError(errno(*__errno_location ()), eErrorTypePOSIX);
778 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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to save the current directory"
, error); } while (0)
;
779 return error;
780 }
781
782 if (::chdir(working_dir.GetCString()) == -1) {
783 error.SetError(errno(*__errno_location ()), eErrorTypePOSIX);
784 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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change working directory to {1}"
, error, working_dir); } while (0)
785 error, working_dir)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change working directory to {1}"
, error, working_dir); } while (0)
;
786 return error;
787 }
788#endif
789 }
790
791 ::pid_t result_pid = LLDB_INVALID_PROCESS_ID0;
792 const size_t num_file_actions = launch_info.GetNumFileActions();
793 if (num_file_actions > 0) {
794 posix_spawn_file_actions_t file_actions;
795 error.SetError(::posix_spawn_file_actions_init(&file_actions),
796 eErrorTypePOSIX);
797 if (error.Fail()) {
798 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )"
, error); } while (0)
799 "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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )"
, error); } while (0)
800 error)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )"
, error); } while (0)
;
801 return error;
802 }
803
804 // Make a quick class that will cleanup the posix spawn attributes in case
805 // we return in the middle of this function.
806 lldb_utility::CleanUp<posix_spawn_file_actions_t *, int>
807 posix_spawn_file_actions_cleanup(&file_actions,
808 posix_spawn_file_actions_destroy);
809
810 for (size_t i = 0; i < num_file_actions; ++i) {
811 const FileAction *launch_file_action =
812 launch_info.GetFileActionAtIndex(i);
813 if (launch_file_action) {
814 if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log,
815 error))
816 return error;
817 }
818 }
819
820 error.SetError(
821 ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp),
822 eErrorTypePOSIX);
823
824 if (error.Fail()) {
825 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~svn298304/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 "file_actions = {3}, "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/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 "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~svn298304/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 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~svn298304/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)
;
829 if (log) {
830 for (int ii = 0; argv[ii]; ++ii)
831 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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "argv[{0}] = '{1}'", ii, argv[ii]); } while (
0)
;
832 }
833 }
834
835 } else {
836 error.SetError(
837 ::posix_spawnp(&result_pid, exe_path, NULL__null, &attr, argv, envp),
838 eErrorTypePOSIX);
839
840 if (error.Fail()) {
841 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~svn298304/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 "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~svn298304/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 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~svn298304/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)
;
844 if (log) {
845 for (int ii = 0; argv[ii]; ++ii)
846 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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "argv[{0}] = '{1}'", ii, argv[ii]); } while (
0)
;
847 }
848 }
849 }
850 pid = result_pid;
851
852 if (working_dir) {
853#if defined(__APPLE__)
854 // No more thread specific current working directory
855 __pthread_fchdir(-1);
856#else
857 if (::chdir(current_dir) == -1 && error.Success()) {
858 error.SetError(errno(*__errno_location ()), eErrorTypePOSIX);
859 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/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: {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~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change current directory back to {1}"
, error, current_dir); } while (0)
861 error, current_dir)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/tools/lldb/source/Host/common/Host.cpp"
, __FUNCTION__, "error: {0}, unable to change current directory back to {1}"
, error, current_dir); } while (0)
;
862 }
863#endif
864 }
865
866 return error;
867}
868
869bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info,
870 Log *log, Error &error) {
871 if (info == NULL__null)
872 return false;
873
874 posix_spawn_file_actions_t *file_actions =
875 reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions);
876
877 switch (info->GetAction()) {
878 case FileAction::eFileActionNone:
879 error.Clear();
880 break;
881
882 case FileAction::eFileActionClose:
883 if (info->GetFD() == -1)
884 error.SetErrorString(
885 "invalid fd for posix_spawn_file_actions_addclose(...)");
886 else {
887 error.SetError(
888 ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()),
889 eErrorTypePOSIX);
890 if (error.Fail())
891 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~svn298304/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 "(action={1}, fd={2})",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/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 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~svn298304/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)
;
894 }
895 break;
896
897 case FileAction::eFileActionDuplicate:
898 if (info->GetFD() == -1)
899 error.SetErrorString(
900 "invalid fd for posix_spawn_file_actions_adddup2(...)");
901 else if (info->GetActionArgument() == -1)
902 error.SetErrorString(
903 "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
904 else {
905 error.SetError(
906 ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(),
907 info->GetActionArgument()),
908 eErrorTypePOSIX);
909 if (error.Fail())
910 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~svn298304/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 "(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~svn298304/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 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~svn298304/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)
;
913 }
914 break;
915
916 case FileAction::eFileActionOpen:
917 if (info->GetFD() == -1)
918 error.SetErrorString(
919 "invalid fd in posix_spawn_file_actions_addopen(...)");
920 else {
921 int oflag = info->GetActionArgument();
922
923 mode_t mode = 0;
924
925 if (oflag & O_CREAT0100)
926 mode = 0640;
927
928 error.SetError(::posix_spawn_file_actions_addopen(
929 file_actions, info->GetFD(),
930 info->GetPath().str().c_str(), oflag, mode),
931 eErrorTypePOSIX);
932 if (error.Fail())
933 LLDB_LOG(do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/tmp/buildd/llvm-toolchain-snapshot-5.0~svn298304/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 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~svn298304/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 "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~svn298304/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 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~svn298304/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)
;
937 }
938 break;
939 }
940 return error.Success();
941}
942#endif // !defined(__ANDROID__)
943#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) ||
944 // defined (__GLIBC__) || defined(__NetBSD__)
945
946#if defined(__linux__1) || defined(__FreeBSD__) || defined(__GLIBC__2) || \
947 defined(__NetBSD__) || defined(_WIN32)
948// The functions below implement process launching via posix_spawn() for Linux,
949// FreeBSD and NetBSD.
950
951Error Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
952 std::unique_ptr<ProcessLauncher> delegate_launcher;
953#if defined(_WIN32)
954 delegate_launcher.reset(new ProcessLauncherWindows());
955#elif defined(__linux__1) || defined(__NetBSD__)
956 delegate_launcher.reset(new ProcessLauncherPosixFork());
957#else
958 delegate_launcher.reset(new ProcessLauncherPosix());
959#endif
960 MonitoringProcessLauncher launcher(std::move(delegate_launcher));
961
962 Error error;
963 HostProcess process = launcher.LaunchProcess(launch_info, error);
964
965 // TODO(zturner): It would be better if the entire HostProcess were returned
966 // instead of writing
967 // it into this structure.
968 launch_info.SetProcessID(process.GetProcessId());
969
970 return error;
971}
972#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
973
974#ifndef _WIN32
975void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); }
976
977#endif
978
979#if !defined(__APPLE__)
980bool Host::OpenFileInExternalEditor(const FileSpec &file_spec,
981 uint32_t line_no) {
982 return false;
983}
984
985#endif
986
987const UnixSignalsSP &Host::GetUnixSignals() {
988 static const auto s_unix_signals_sp =
989 UnixSignals::Create(HostInfo::GetArchitecture());
990 return s_unix_signals_sp;
991}