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