Process.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
  4. * Copyright (c) 2023-2024, Sam Atkins <atkinssj@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/ByteString.h>
  9. #include <AK/ScopeGuard.h>
  10. #include <AK/String.h>
  11. #include <AK/Vector.h>
  12. #include <LibCore/Environment.h>
  13. #include <LibCore/File.h>
  14. #include <LibCore/Process.h>
  15. #include <LibCore/System.h>
  16. #include <errno.h>
  17. #include <spawn.h>
  18. #include <unistd.h>
  19. #if defined(AK_OS_SERENITY)
  20. # include <serenity.h>
  21. # include <sys/prctl.h>
  22. # include <syscall.h>
  23. #elif defined(AK_OS_BSD_GENERIC) && !defined(AK_OS_SOLARIS)
  24. # include <sys/sysctl.h>
  25. #elif defined(AK_OS_GNU_HURD)
  26. extern "C" {
  27. # include <hurd.h>
  28. }
  29. #endif
  30. #if defined(AK_OS_FREEBSD)
  31. # include <sys/user.h>
  32. #endif
  33. namespace Core {
  34. struct ArgvList {
  35. ByteString m_path;
  36. Vector<char const*, 10> m_argv;
  37. ArgvList(ByteString path, size_t size)
  38. : m_path { path }
  39. {
  40. m_argv.ensure_capacity(size + 2);
  41. m_argv.append(m_path.characters());
  42. }
  43. void append(char const* arg)
  44. {
  45. m_argv.append(arg);
  46. }
  47. Span<char const*> get()
  48. {
  49. if (m_argv.is_empty() || m_argv.last() != nullptr)
  50. m_argv.append(nullptr);
  51. return m_argv;
  52. }
  53. };
  54. ErrorOr<Process> Process::spawn(ProcessSpawnOptions const& options)
  55. {
  56. #define CHECK(invocation) \
  57. if (int returned_errno = (invocation)) \
  58. return Error::from_errno(returned_errno);
  59. posix_spawn_file_actions_t spawn_actions;
  60. CHECK(posix_spawn_file_actions_init(&spawn_actions));
  61. ScopeGuard cleanup_spawn_actions = [&] {
  62. posix_spawn_file_actions_destroy(&spawn_actions);
  63. };
  64. if (options.working_directory.has_value()) {
  65. #ifdef AK_OS_SERENITY
  66. CHECK(posix_spawn_file_actions_addchdir(&spawn_actions, options.working_directory->characters()));
  67. #else
  68. // FIXME: Support ProcessSpawnOptions::working_directory n platforms that support it.
  69. TODO();
  70. #endif
  71. }
  72. for (auto const& file_action : options.file_actions) {
  73. TRY(file_action.visit(
  74. [&](FileAction::OpenFile const& action) -> ErrorOr<void> {
  75. CHECK(posix_spawn_file_actions_addopen(
  76. &spawn_actions,
  77. action.fd,
  78. action.path.characters(),
  79. File::open_mode_to_options(action.mode | Core::File::OpenMode::KeepOnExec),
  80. action.permissions));
  81. return {};
  82. }));
  83. }
  84. #undef CHECK
  85. ArgvList argv_list(options.executable, options.arguments.size());
  86. for (auto const& argument : options.arguments)
  87. argv_list.append(argument.characters());
  88. pid_t pid;
  89. if (options.search_for_executable_in_path) {
  90. pid = TRY(System::posix_spawnp(options.executable.view(), &spawn_actions, nullptr, const_cast<char**>(argv_list.get().data()), Core::Environment::raw_environ()));
  91. } else {
  92. pid = TRY(System::posix_spawn(options.executable.view(), &spawn_actions, nullptr, const_cast<char**>(argv_list.get().data()), Core::Environment::raw_environ()));
  93. }
  94. return Process { pid };
  95. }
  96. ErrorOr<pid_t> Process::spawn(StringView path, ReadonlySpan<ByteString> arguments, ByteString working_directory, KeepAsChild keep_as_child)
  97. {
  98. auto process = TRY(spawn({
  99. .executable = path,
  100. .arguments = Vector<ByteString> { arguments },
  101. .working_directory = working_directory.is_empty() ? Optional<ByteString> {} : Optional<ByteString> { working_directory },
  102. }));
  103. if (keep_as_child == KeepAsChild::No)
  104. TRY(process.disown());
  105. else {
  106. // FIXME: This won't be needed if return value is changed to Process.
  107. process.m_should_disown = false;
  108. }
  109. return process.pid();
  110. }
  111. ErrorOr<pid_t> Process::spawn(StringView path, ReadonlySpan<StringView> arguments, ByteString working_directory, KeepAsChild keep_as_child)
  112. {
  113. Vector<ByteString> backing_strings;
  114. backing_strings.ensure_capacity(arguments.size());
  115. for (auto const& argument : arguments)
  116. backing_strings.append(argument);
  117. auto process = TRY(spawn({
  118. .executable = path,
  119. .arguments = backing_strings,
  120. .working_directory = working_directory.is_empty() ? Optional<ByteString> {} : Optional<ByteString> { working_directory },
  121. }));
  122. if (keep_as_child == KeepAsChild::No)
  123. TRY(process.disown());
  124. else
  125. process.m_should_disown = false;
  126. return process.pid();
  127. }
  128. ErrorOr<pid_t> Process::spawn(StringView path, ReadonlySpan<char const*> arguments, ByteString working_directory, KeepAsChild keep_as_child)
  129. {
  130. Vector<ByteString> backing_strings;
  131. backing_strings.ensure_capacity(arguments.size());
  132. for (auto const& argument : arguments)
  133. backing_strings.append(argument);
  134. auto process = TRY(spawn({
  135. .executable = path,
  136. .arguments = backing_strings,
  137. .working_directory = working_directory.is_empty() ? Optional<ByteString> {} : Optional<ByteString> { working_directory },
  138. }));
  139. if (keep_as_child == KeepAsChild::No)
  140. TRY(process.disown());
  141. else
  142. process.m_should_disown = false;
  143. return process.pid();
  144. }
  145. ErrorOr<String> Process::get_name()
  146. {
  147. #if defined(AK_OS_SERENITY)
  148. char buffer[BUFSIZ];
  149. int rc = get_process_name(buffer, BUFSIZ);
  150. if (rc != 0)
  151. return Error::from_syscall("get_process_name"sv, -rc);
  152. return String::from_utf8(StringView { buffer, strlen(buffer) });
  153. #elif defined(AK_LIBC_GLIBC) || (defined(AK_OS_LINUX) && !defined(AK_OS_ANDROID))
  154. return String::from_utf8(StringView { program_invocation_name, strlen(program_invocation_name) });
  155. #elif defined(AK_OS_BSD_GENERIC) || defined(AK_OS_HAIKU)
  156. auto const* progname = getprogname();
  157. return String::from_utf8(StringView { progname, strlen(progname) });
  158. #else
  159. // FIXME: Implement Process::get_name() for other platforms.
  160. return "???"_string;
  161. #endif
  162. }
  163. ErrorOr<void> Process::set_name([[maybe_unused]] StringView name, [[maybe_unused]] SetThreadName set_thread_name)
  164. {
  165. #if defined(AK_OS_SERENITY)
  166. int rc = set_process_name(name.characters_without_null_termination(), name.length());
  167. if (rc != 0)
  168. return Error::from_syscall("set_process_name"sv, -rc);
  169. if (set_thread_name == SetThreadName::No)
  170. return {};
  171. rc = prctl(PR_SET_THREAD_NAME, gettid(), name.characters_without_null_termination(), name.length());
  172. if (rc != 0)
  173. return Error::from_syscall("set_thread_name"sv, -rc);
  174. return {};
  175. #else
  176. // FIXME: Implement Process::set_name() for other platforms.
  177. return {};
  178. #endif
  179. }
  180. ErrorOr<bool> Process::is_being_debugged()
  181. {
  182. #if defined(AK_OS_LINUX)
  183. auto unbuffered_status_file = TRY(Core::File::open("/proc/self/status"sv, Core::File::OpenMode::Read));
  184. auto status_file = TRY(Core::InputBufferedFile::create(move(unbuffered_status_file)));
  185. auto buffer = TRY(ByteBuffer::create_uninitialized(4096));
  186. while (TRY(status_file->can_read_line())) {
  187. auto line = TRY(status_file->read_line(buffer));
  188. auto const parts = line.split_view(':');
  189. if (parts.size() < 2 || parts[0] != "TracerPid"sv)
  190. continue;
  191. auto tracer_pid = parts[1].to_number<u32>();
  192. return (tracer_pid != 0UL);
  193. }
  194. return false;
  195. #elif defined(AK_OS_GNU_HURD)
  196. process_t proc = getproc();
  197. if (!MACH_PORT_VALID(proc))
  198. return Error::from_syscall("getproc"sv, -errno);
  199. int flags = PI_FETCH_TASKINFO;
  200. // We're going to ask the proc server for the info about our process,
  201. // and it is going to reply, placing the info into a buffer. It can
  202. // either fill in (overwrite) the buffer we provide to it (called pi_buffer
  203. // below), or allocate (as if with mmap or vm_allocate) a new buffer.
  204. // The buffer is really of type struct procinfo[], but it's transferred
  205. // over IPC as int[]. We pass in a double pointer (int** pi_array) that
  206. // initially points to our pi_buffer, but the call will update it to
  207. // point to the newly allocated buffer if it ends up making one.
  208. struct procinfo pi_buffer = {};
  209. int* pi_array = reinterpret_cast<int*>(&pi_buffer);
  210. mach_msg_type_number_t pi_array_len = sizeof(pi_buffer) / sizeof(int);
  211. data_t waits = nullptr;
  212. mach_msg_type_number_t waits_len = 0;
  213. kern_return_t err = proc_getprocinfo(proc, getpid(), &flags, &pi_array, &pi_array_len, &waits, &waits_len);
  214. mach_port_deallocate(mach_task_self(), proc);
  215. if (err) {
  216. __hurd_fail(static_cast<error_t>(err));
  217. return Error::from_syscall("proc_getprocinfo"sv, -errno);
  218. }
  219. // Now cast the returned buffer pointer back to struct procinfo, and
  220. // read the info we're interested in (the PI_TRACED flag) from there.
  221. VERIFY(pi_array_len >= sizeof(struct procinfo));
  222. struct procinfo* procinfo = reinterpret_cast<struct procinfo*>(pi_array);
  223. bool traced = procinfo->state & PI_TRACED;
  224. // If the returned buffer is not the one we allocated on the stack,
  225. // we should unmap it.
  226. if (procinfo != &pi_buffer)
  227. (void)System::munmap(pi_array, pi_array_len * sizeof(int));
  228. if (waits)
  229. (void)System::munmap(waits, waits_len);
  230. return traced;
  231. #elif defined(AK_OS_MACOS) || defined(AK_OS_FREEBSD)
  232. // https://developer.apple.com/library/archive/qa/qa1361/_index.html
  233. int mib[4] = {};
  234. struct kinfo_proc info = {};
  235. size_t size = sizeof(info);
  236. // Initialize mib, which tells sysctl the info we want, in this case
  237. // we're looking for information about a specific process ID.
  238. mib[0] = CTL_KERN;
  239. mib[1] = KERN_PROC;
  240. mib[2] = KERN_PROC_PID;
  241. mib[3] = getpid();
  242. if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) < 0)
  243. return Error::from_syscall("sysctl"sv, -errno);
  244. // We're being debugged if the P_TRACED flag is set.
  245. # if defined(AK_OS_MACOS)
  246. return ((info.kp_proc.p_flag & P_TRACED) != 0);
  247. # elif defined(AK_OS_FREEBSD)
  248. return ((info.ki_flag & P_TRACED) != 0);
  249. # endif
  250. #endif
  251. // FIXME: Implement this for more platforms.
  252. return Error::from_string_view("Platform does not support checking for debugger"sv);
  253. }
  254. // Forces the process to sleep until a debugger is attached, then breaks.
  255. void Process::wait_for_debugger_and_break()
  256. {
  257. bool should_print_process_info { true };
  258. for (;;) {
  259. auto check = Process::is_being_debugged();
  260. if (check.is_error()) {
  261. dbgln("Cannot wait for debugger: {}. Continuing.", check.release_error());
  262. return;
  263. }
  264. if (check.value()) {
  265. kill(getpid(), SIGTRAP);
  266. return;
  267. }
  268. if (should_print_process_info) {
  269. dbgln("Process {} with pid {} is sleeping, waiting for debugger.", Process::get_name(), getpid());
  270. should_print_process_info = false;
  271. }
  272. ::usleep(100 * 1000);
  273. }
  274. }
  275. ErrorOr<void> Process::disown()
  276. {
  277. if (m_pid != 0 && m_should_disown) {
  278. #ifdef AK_OS_SERENITY
  279. TRY(System::disown(m_pid));
  280. #else
  281. // FIXME: Support disown outside Serenity.
  282. #endif
  283. m_should_disown = false;
  284. return {};
  285. } else {
  286. return Error::from_errno(EINVAL);
  287. }
  288. }
  289. ErrorOr<bool> Process::wait_for_termination()
  290. {
  291. VERIFY(m_pid > 0);
  292. bool exited_with_code_0 = true;
  293. int status;
  294. if (waitpid(m_pid, &status, 0) == -1)
  295. return Error::from_syscall("waitpid"sv, errno);
  296. if (WIFEXITED(status)) {
  297. exited_with_code_0 &= WEXITSTATUS(status) == 0;
  298. } else if (WIFSIGNALED(status)) {
  299. exited_with_code_0 = false;
  300. } else if (WIFSTOPPED(status)) {
  301. // This is only possible if the child process is being traced by us.
  302. VERIFY_NOT_REACHED();
  303. } else {
  304. VERIFY_NOT_REACHED();
  305. }
  306. m_should_disown = false;
  307. return exited_with_code_0;
  308. }
  309. }